comply

package module
v0.0.0-...-0c7c43c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2019 License: GPL-3.0 Imports: 4 Imported by: 0

README

go-comply

Myriad RFC-dictated interfaces, methods and imperatives

Build Status Reference Go Report Card

Created and currently maintained by Jesse Coretta (subcon42).

Status

This project is EXTREMELY ALPHA; you are warned of potential package volatility.

Synopsis

go-comply/comply is a framework designed by Jesse Coretta for the purpose of allowing user-authored RFC-centric "modules" to be contributed by various subject matter expects in the Go world. These modules would be stored within the go-comply/comply package repository, and collectively would represent a "suite of compliance methods".

Use of these modules would allow the analysis of a given byte sequence or sequences. Each module, being written in strict spirit of a specific RFC, would "judge" these candidate sequences for compliancy.

Modules are written based on review of RFC dictates and imperatives; no RFC data is "scraped" nor "parsed" externally. It all comes from research and implementation by one or more persons familiar with both Go and the RFC(s) in question.

The essential goal of this entire endeavor is to afford easy compliance checking without long nights of RFC research.

Features

  • plugin use for user-controllable memory footprint based on their compliancy needs
  • Concurrency-safe thanks to use of sync.Map
  • Built-in functions for contributors to use in their own modules, thus reducing coding time
  • URL production for "See Also" references (e.g: refers one back to RFCXXXX on IETF's RFC Website)
  • Capable of fluent and non-fluent styles of use
  • Voluminous documentation

Roadmap

  • Far-broader RFC coverage
  • More Test and Example files
  • An entirely separate package that uses go-comply for specific reasons
  • Efficiency improvements

Basic Example

package main

import (
        "fmt"
        "github.com/go-comply/comply"
)

func main() {

        // uncomment for more chatter
        //comply.Debug(true)

        // Create a *CompMachine (Compliance Machine); only
        // needed once ...
        machine, err := comply.New(0)
        if err != nil {
                fmt.Println(err)
                return
        }

        // Uncomment to see if a given RFC is simply available for import
        //avail := machine.RFC(65530).Available()
        //if !avail {
        //    fmt.Printf("Can't find .so file for RFC%d", 65530)
        //    return
        //}

        // Initialize a known-ready RFC; this will load the exported subpackage
        // elements into memory, and ready for use!
        err = machine.Init(1034)
        if err != nil {
                fmt.Println(err)
                return
        }

        // One is a good FQDN, and the other is bad due to an identical brother adjacency
        // mentioned in RFC 1034 Section 3.1 (e.g: a.b.c (good) vs. a.a.c (bad))
        var goodFQDN [][]uint8 = [][]uint8{[]uint8{uint8('a')}, []uint8{uint8('b')}, []uint8{uint8('c')}}
        var badFQDN [][]uint8 = [][]uint8{[]uint8{uint8('a')}, []uint8{uint8('a')}, []uint8{uint8('c')}}

        // Check our good one ...
        verdict, err := machine.RFC(1034).Compliant(`3.1`, comply.Must(), goodFQDN)
        if err != nil {
                fmt.Printf("Compliant: %t - %s\n", verdict, err.Error())
                return
        }

        // Check our bad one ...
        verdict, err = machine.RFC(1034).Compliant(`3.1`, comply.Must(), badFQDN)
        if err != nil {
                fmt.Printf("Compliant: %t - %s\n", verdict, err.Error())
                return
        }

        // Get the official RFC document at this URL for more information ...
        seeAlso := machine.RFC(1034).URL()
        fmt.Printf("Compliant: %t\nFor more information, see %s\n\n", verdict, seeAlso)

}

Documentation

Overview

Package comply provides standards-specific parsing and validation methods. With continuous RFC reviews and community contributions, this section is likely to grow far into the future.

The goal of this project is to grow and house contributions from the community, or established technical authorities, around particular subject matters described in one or more RFCs. These contributions would manifest here, as Go code.

It should be stated that NO RFCs are stored in this repository whatsoever! This repository exists because of one simple reason: painstaking, meticulous research was conducted.

Project Theory

No one likes reading RFCs, right? But while they're a burden, they can be critically helpful, particularly when dealing with low-level technologies.

When a particular subject is sufficiently understood, a contributor can author code (either by adding to an existing RFC module, or by creating a new module that was previously nonexistent) to handle a particular section, or sections, of an RFC.

Not every RFC would make sense for a contributor to implement as a module. Some RFCs have no "parsing logic" upon which to base new methods.

Furthermore, while there are extremely suitable, highly-technical RFCs would be completely appropriate for implementation in this project, not every section (e.g: 1.4.10.2) would make sense to implement. Some are merely advisories pertaining to the roadmap of a standard, others contain foreword-type text-walls that have no practical application in the context of this package.

Thus, authoring a module is entirely up to the discretion, interpretation and feasability assessment of the contributor(s) in question.

Contribution Registration

When a contributor successfully produces an approved RFC module for placement in this project's repository, it will become available to all who download the go-comply/comply package. This does not mean it is ready for use.

The reason for this is the sheer number of RFCs in existence, and the prospect of many more to come (hence our opening statement). It would be dubious, at best, to blindly do an import for present RFC modules them upon package "execution".

Instead, the inclusion of any given module is user-invoked. This is where go's plugin package comes into play, and why modules need to be written in a fairly specific way.

Modular Efficiency

Let's say "Contributor Courtney" comes along, and she wants to contribute a very reliable LDAPv3 Search Filter parser (as is described in RFC 2254). She does so, the pull request was eventually approved and merged into go-comply/comply. Great so far.

While her module was written very efficiently, some may perceive it to be rather large in the grand scheme of memory use (as an example), and that it should not be implicitly loaded. Many people won't be using go-comply/comply to parse any LDAP-related sequences whatsoever, thus why should they be charged in memory?

One day, "User Kelly" comes along, and she works in the engineering's compliance department for some government contractor somewhere. Part of her job is ensuring particular pieces of publicly-available technical data (say, for example, public hostnames) are RFC 952 compliant. She finds that someone has contributed an RFC 952 compliance module, and according to the documentation, it parses information in a manner consistent with Kelly's mandates.

Kelly can write up a small amount of Go code to do the following:

* import "github.com/go-comply/comply"

* Write a method to load the RFC 952 module simply via query of int(952)

* Once loaded, and once she has read the documentation, parse whatever byte sequences that come her way

Note that in this scenario, she hasn't loaded Courtney's LDAPv3 module because she never asked for it! Thus no memory is wasted on irrelevant content.

This is a particularly important point if, somehow, a central compliance server were setup that interfaced with go-comply/comply to parse large volumes of data that is very specific in nature (say, for Kelly's entire engineering department because her script was so awesome, everyone wanted a piece of it).

RFC Lifecycles

RFCs eventually become obsolete, or they are "updated by" one or more entirely new RFC incarnations at some later point.

Contributors should rarely be found in a position to have to go back and "change something" in their modules, but IF that is the case someday, contributors must keep a keen eye on where one RFC ends and the other begins.

The act of an RFC being "updated by" another RFC does not necessarily imply any supplantation, but it may mean one or more portions have been clarified or maybe even extended, in such a way that necessitates code changes.

A contributor's module should reflect the nature of the most recent copy of *only* the RFC in question. Whatever other RFCs exist are just that: *OTHER* RFCs. So, the contributor(s) should write one for them as well (if practical).

Obsolescence is another key point: a module whose RFC has been declared obsolete is NOT useless! Contributors should not delete them from the repo, nor would the core maintainers do so (for that reason alone).

If this obsolescence occurs in the midst of a technological "transition", maybe even in grand scale, diagnostically it would make sense for engineers to have a means to prove that a particular byte sequence (for example) is compliant with an OBSOLETE standard but not a NEW one. The concept of troubleshooting in the capacity of support teams comes to mind. Or what about practical historical interests, maybe even in a training capacity? You never know ...

Authorship Guidelines

This section aims to get the hard requirements declared. Each set of guidelines falls beneath the nomenclature established in RFC 2119's imperatives for clarity.

Must

* Modules must absolutely be documented in a strict Godoc-compliant fashion. Just because the module is imported-on-demand and largely hands-free, you're still expected to talk about your module. Examples include but are not limited to:

What packages are imported (if any)?

What will it do? How does it work internally?

Are there IO concerns? Is it thread-safe?

How does it expect data to be submitted (e.g: as a string, a [][]uint8, etc ...)?

* You must name your folder RFCXXXX, where XXXX represents the digit sequence of the RFC in question should be your module's folder name. It will reside on the same level as all of the other RFC-prefixed folders. Example:

go-comply/comply/RFCXXXX

* Folder must contain a .gitignore file that expressly ignores .so files

* All module files must all be of the "main" namespace

YES:  package main

NO:   package rfcXXXX

* Modules must cover only directly-stated section-based requirements

* In other words, your code should be "by the book" -- literally

* Each module must have no more than one method per Imperative per section

YES: SectionX.Y.Y -> Must -> func(...interface{}) (bool, error)
... and ...
YES: SectionX.Y.Y -> MustNot -> func(...interface{}) (bool, error)

NO: SectionX.Y.Y -> Must -> func(...interface{}) (bool, error)
... and ...
NO: SectionX.Y.Y -> Must -> func(...interface{}) (bool, error)

* All of the Section-based Imperative-to-Function storage must occur within a basic map[string]map[uint]func(...interface{}) (bool, error), which will be imported by the core comply framework for ingestion

MustNot

* Contributed subpackages must not import other go-comply/comply modules, including the comply package itself, EVER. The "import flow" must flow from the inside out as shown in the diagram below. Note the ONLY EXCEPTION is the go-comply/comply/common package; contributed modules and even the comply base package can (and should) use this package.

YES:  comply  (importer) <-imported-- rfcXXXX (exporter)

YES:  comply  (importer) <-imported-- common  (exporter)

YES:  RFCXXXX (importer) <-imported-- common  (exporter)

NO:   RFCXXXX (importer) <-imported-- comply  (exporter)

NO:   RFCXXXX (importer) <-imported-- RFCXXXY (exporter)

* Contributed subpackages must not must not include pre-compiled *.so files. This is meant for the user's machine to handle at install time! This is mainly due to security reasons, since a *.so file is essentially a black box of self-executing code (when deliberately called by the user)

Should

* Modules should use as few imported packages as possible, and they should ideally be limited to built-in or extremely well-known packages

* Modules should be written with the understanding that the aim is to parse well-known strings, as well as numerical and byte sequences on their most elementary levels (according to the dictates of a given RFC). As such, the need for exotic packages should be extremely rare

* Modules should be written with performance in mind; less IO, less cyclical complexity, etc., is always preferred

May

* Modules may have as many files inside as desired; contributors may split-up their code as they see fit

* Contributors may augment their folder's respective .gitignore file to exclude other system files per their OS/setup, so long as the .so rule is not removed

* Modules may contain .go files named anything the contributor(s) wish, but are encouraged to stick with intuitive, relevant terms, e.g:

RFCXXXX/doc.go

RFCXXXX/parse.go

RFCXXXX/error.go

* Contributors may lay-out internal "worker" methods any way they wish; so long as the top-level methods conform to the specifications defined in the Must section above, the "inner workings" of such functions may be of, stylistically, any design.

Credit

Conceived, implemented and maintained by Jesse Coretta (subcon42).

Help Wanted

Know an RFC really well? Contributions, input and general interest in this project is strongly encouraged and always welcome.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Debug

func Debug(b bool)

Debug will allow a boolean toggle declaring whether extended debug output should be printed to Stdout.

func May

func May() uint

May Imperative is described in RFC 2119 ABSTRACT Sections 1-5. This will return the associated uint value.

func Must

func Must() uint

Must Imperative is described in RFC 2119 ABSTRACT Sections 1-5. This will return the associated uint value.

func MustNot

func MustNot() uint

MustNot Imperative is described in RFC 2119 ABSTRACT Sections 1-5. This will return the associated uint value.

func Should

func Should() uint

Should Imperative is described in RFC 2119 ABSTRACT Sections 1-5. This will return the associated uint value.

func ShouldNot

func ShouldNot() uint

ShouldNot Imperative is described in RFC 2119 ABSTRACT Sections 1-5. This will return the associated uint value.

Types

type CompMachine

type CompMachine struct {
	// contains filtered or unexported fields
}

CompMachine (Compliance Machine) provides transport of command and input values to the necessary internal methods. It is meant to be created by way of Is(), Get() or Set() methods.

func Get

func Get(i ...interface{}) *CompMachine

Get allows the retrieval of particular items or values.

func Is

func Is(i ...interface{}) *CompMachine

Is allows the querying or checking of particular conditions or states.

func New

func New(i ...interface{}) (*CompMachine, error)

New produces a new instance of *CompMachine. It is from this object that subsequent methods are extended.

Should an error occur, one is returned. Else, nil.

func Set

func Set(i ...interface{}) *CompMachine

Set allows the configuration of particular items or values.

func (*CompMachine) Init

func (c *CompMachine) Init(r ...interface{}) (err error)

Init shall initialize one or more RFCs (by number) within the receiver instance of *CompMachine.

An error is returned should any issues be encountered, else nil.

func (*CompMachine) RFC

func (c *CompMachine) RFC(r interface{}) *RFCEntity

RFC (which is extended by an instance of *CompMachine) allows RFC-specific methods to be extended:

* URL() * Compliant() * Available() * Registered()

type RFCEntity

type RFCEntity struct {
	// contains filtered or unexported fields
}

RFCEntity provides RFC data storage handling methods, and is meant to be created via CompMachine.RFC.

func (RFCEntity) Available

func (r RFCEntity) Available() bool

Available shall return a bool indicative of whether the RFC number defined in the receiver instance of *RFCEntity is present as a module on the system in question.

func (*RFCEntity) Compliant

func (r *RFCEntity) Compliant(s string, id uint, args ...interface{}) (bool, error)

Compliant shall execute compliance checks registered by the RFC module specified within the receiver instance of *RFCEntity. A section string, imperative uint and per-module-specific arguments (passed as an unspecified array of interfaces (...interface{})), are the required arguments.

A bool is returned indicating whether compliance checks passed; an error is non-nil if either compliance checks simply failed, or their ability to run was prohibited somehow.

func (RFCEntity) Registered

func (r RFCEntity) Registered() bool

Registered shall return a bool indicative of whether the RFC number defined in the receiver instance of *RFCEntity is registered in-memory and ready for use.

func (RFCEntity) URL

func (r RFCEntity) URL() string

URL returns the ietf.org URL as a string for the RFC in question.

Directories

Path Synopsis
Package rfc1034 encompasses portions of: RFC 1034 - "Domain Names - Concepts and Facilities" This subpackage implements relevant methods and checks for validating the composition of a candidate RFC 1034 Absolute Name (aka FQDN).
Package rfc1034 encompasses portions of: RFC 1034 - "Domain Names - Concepts and Facilities" This subpackage implements relevant methods and checks for validating the composition of a candidate RFC 1034 Absolute Name (aka FQDN).
Package rfc2119 encompasses portions of: RFC 2119 - "Key words for use in RFCs to Indicate Requirement Levels" Summary This subpackage implements relevant key words for imperative function declaration.
Package rfc2119 encompasses portions of: RFC 2119 - "Key words for use in RFCs to Indicate Requirement Levels" Summary This subpackage implements relevant key words for imperative function declaration.
Package rfc65530 encompasses portions of no RFC in reality.
Package rfc65530 encompasses portions of no RFC in reality.
Package rfc952 encompasses portions of: RFC 952 - "DOD INTERNET HOST TABLE SPECIFICATION" This subpackage implements relevant methods and checks for Assumptions Section 1 defined in said document.
Package rfc952 encompasses portions of: RFC 952 - "DOD INTERNET HOST TABLE SPECIFICATION" This subpackage implements relevant methods and checks for Assumptions Section 1 defined in said document.
Package common provides complimentary types and methods that are available to other modules as a direct import, e.g: import "github.com/go-comply/comply/common" This is the ONLY package directory (inside of the comply suite) that contributor modules (e.g: RFC1034) may import.
Package common provides complimentary types and methods that are available to other modules as a direct import, e.g: import "github.com/go-comply/comply/common" This is the ONLY package directory (inside of the comply suite) that contributor modules (e.g: RFC1034) may import.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL