Skip to content

Commit

Permalink
Merge pull request #127 from boxboat/feature-cli
Browse files Browse the repository at this point in the history
Feature cli (#56)
  • Loading branch information
adityasaky authored Sep 17, 2021
2 parents 02b98c8 + 6862711 commit 6b6d786
Show file tree
Hide file tree
Showing 13 changed files with 1,800 additions and 8 deletions.
157 changes: 157 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Common Certificate Attributes
TRUST_DOMAIN_FQDN := example.com
DEFAULT_BITS := 2048
DEFAULT_MD := sha512
ORGANIZATIONAL_UNIT := example
ORGANIZATION := example
ROOT_DAYS := 3650
INTERMEDIATE_DAYS := 3650
LEAF_DAYS := 1

# Template Locations
OPENSSL_TMPL := ./certs/openssl.cnf.tmpl
LAYOUT_TMPL := ./certs/layout.tmpl

build: modules
@mkdir -p bin
@go build -o ./bin/in-toto ./cmd/in-toto

modules:
@go mod tidy

clean: clean-certs clean-test-files
@rm -rf ./bin

clean-certs:
@rm -rf ./certs/*.pem ./certs/*.srl ./certs/*.cnf

clean-test-files:
@rm -rf ./test/tmp
@rm -rf ./untar.link
@rm -rf ./.srl

test: go-test test-verify

go-test:
@go test ./...

test-sign: build generate_layout
# Running test-sign
@./bin/in-toto sign -f ./test/tmp/test.layout -k ./certs/example.com.layout.key.pem -o ./test/tmp/signed.layout

test-record: build generate_layout
# Running record start
@./bin/in-toto record start -n write-code -c ./certs/example.com.write-code.cert.pem -k ./certs/example.com.write-code.key.pem -d ./test/tmp
# Record running step
@echo goodbye > ./test/tmp/foo.py
# Running record stop
@./bin/in-toto record stop -n write-code -c ./certs/example.com.write-code.cert.pem -p ./test/tmp/foo.py -k ./certs/example.com.write-code.key.pem -d ./test/tmp

test-run: build generate_layout
# Running write code step
@./bin/in-toto run -n write-code -c ./certs/example.com.write-code.cert.pem -k ./certs/example.com.write-code.key.pem -p ./test/tmp/foo.py -d ./test/tmp -- /bin/sh -c "echo hello > ./test/tmp/foo.py"
# Running package step
@./bin/in-toto run -n package -c ./certs/example.com.package.cert.pem -k ./certs/example.com.package.key.pem -m ./test/tmp/foo.py -p ./test/tmp/foo.tar.gz -d ./test/tmp -- tar zcvf ./test/tmp/foo.tar.gz ./test/tmp/foo.py

test-verify: test-sign test-run
# Running test verify
@./bin/in-toto verify -l ./test/tmp/signed.layout -k ./certs/example.com.layout.cert.pem -i ./certs/example.com.intermediate.cert.pem -d ./test/tmp

generate_layout: leaf_certs
@mkdir -p ./test/tmp
$(eval rootca := $(shell ./bin/in-toto key layout ./certs/root.cert.pem | sed -e 's/\\n/\\\\n/g'))
@cat $(LAYOUT_TMPL) | sed -e 's#{{ROOTCA}}#$(rootca)#' > ./test/tmp/test.layout

root-cert:
# Generate root cert openssl conf file
$(call generate_openssl_conf,root)

# Create Root Key
@openssl genrsa -out ./certs/root.key.pem

# Create Root Cert
@openssl req -subj "/C=/ST=/L=/O=$(ORGANIZATION)/OU=$(ORGANIZATIONAL_UNIT)CN=root/" -days $(ROOT_DAYS) -x509 -new \
-key "./certs/root.key.pem" -out "./certs/root.cert.pem" \
-config ./certs/$(TRUST_DOMAIN_FQDN).root.openssl.cnf \
-extensions v3-root

intermediate_cert: root-cert
# Generate intermediate cert openssl conf file
$(call generate_openssl_conf,intermediate)

# Create intermediate key
@openssl genrsa -out ./certs/$(TRUST_DOMAIN_FQDN).intermediate.key.pem

# Generate intermediate CSR
@openssl req -subj "/C=/ST=/L=/O=$(ORGANIZATION)/OU=$(ORGANIZATIONAL_UNIT)CN=$(TRUST_DOMAIN_FQDN)" -new \
-key ./certs/$(TRUST_DOMAIN_FQDN).intermediate.key.pem \
-out ./certs/$(TRUST_DOMAIN_FQDN).intermediate.csr.pem \
-config ./certs/$(TRUST_DOMAIN_FQDN).intermediate.openssl.cnf \
-extensions v3-intermediate

# Sign Intermediate CSR Using Root Certificate
@openssl x509 -days $(INTERMEDIATE_DAYS) -req \
-CAcreateserial \
-CA ./certs/root.cert.pem \
-CAkey ./certs/root.key.pem \
-in ./certs/$(TRUST_DOMAIN_FQDN).intermediate.csr.pem \
-out ./certs/$(TRUST_DOMAIN_FQDN).intermediate.cert.pem \
-extfile ./certs/$(TRUST_DOMAIN_FQDN).intermediate.openssl.cnf \
-extensions v3-intermediate

# Verify intermediate cert was signed by root cert
@openssl verify -CAfile ./certs/root.cert.pem ./certs/$(TRUST_DOMAIN_FQDN).intermediate.cert.pem

leaf_certs: intermediate_cert
$(call generate_leaf_cert,layout)
$(call generate_leaf_cert,write-code)
$(call generate_leaf_cert,package)

define generate_leaf_cert
# Generate leaf cert openssl conf file
$(call generate_openssl_conf,$(1))

# Generate leaf signing key
@openssl genrsa -out ./certs/$(TRUST_DOMAIN_FQDN).$(1).key.pem

# Generate leaf CSR
openssl req -new \
-key ./certs/$(TRUST_DOMAIN_FQDN).$(1).key.pem \
-out ./certs/$(TRUST_DOMAIN_FQDN).$(1).csr.pem \
-config ./certs/$(TRUST_DOMAIN_FQDN).$(1).openssl.cnf \
-extensions v3-leaf

# Sign leaf CSR Using intermediate Certificate
@openssl x509 -days $(LEAF_DAYS) -req \
-CAcreateserial \
-CA ./certs/$(TRUST_DOMAIN_FQDN).intermediate.cert.pem \
-CAkey ./certs/$(TRUST_DOMAIN_FQDN).intermediate.key.pem \
-in ./certs/$(TRUST_DOMAIN_FQDN).$(1).csr.pem \
-out ./certs/$(TRUST_DOMAIN_FQDN).$(1).cert.pem \
-extfile ./certs/$(TRUST_DOMAIN_FQDN).$(1).openssl.cnf \
-extensions v3-leaf

# Create cert bundle for trust domain
cat ./certs/root.cert.pem ./certs/$(TRUST_DOMAIN_FQDN).intermediate.cert.pem > ./certs/$(TRUST_DOMAIN_FQDN).bundle.cert.pem

# Verify leaf cert chain
@openssl verify -CAfile ./certs/$(TRUST_DOMAIN_FQDN).bundle.cert.pem ./certs/$(TRUST_DOMAIN_FQDN).$(1).cert.pem
endef

define generate_openssl_conf
@cat $(OPENSSL_TMPL) | sed -e 's/{{TRUST_DOMAIN_FQDN}}/$(TRUST_DOMAIN_FQDN)/' | \
sed -e 's/{{ORGANIZATIONAL_UNIT}}/$(ORGANIZATIONAL_UNIT)/' | \
sed -e 's/{{ORGANIZATION}}/$(ORGANIZATION)/' | \
sed -e 's/{{DEFUALT_BITS}}/$(DEFAULT_BITS)/' | \
sed -e 's/{{DEFAULT_MD}}/$(DEFAULT_MD)/' | \
sed -e 's/{{SPIFFE_PATH}}/$(1)/' > certs/$(TRUST_DOMAIN_FQDN).$(1).openssl.cnf
endef

.PHONY: help
all: help
help: Makefile
@echo
@echo " Choose a command run in in-toto-golang:"
@echo
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
@echo
206 changes: 206 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,212 @@ func main() {
}
```

## Running the Demo

To run the demo, pull down the source code, install Go, and run `make test-verify`.
This will use openssl to generate a certificate chain.

During the in-toto verification process, `certificate constraints` are checked to ensure the build step link meta-data was signed with the correct SVID.

## Building

Download the source, run `make build`.

## CLI

```text
Usage:
in-toto [command]
Available Commands:
help Help about any command
key Key management commands
record Creates a signed link metadata file in two steps, in order to provide evidence for supply chain steps that cannot be carried out by a single command
run Executes the passed command and records paths and hashes of 'materials'
sign Provides command line interface to sign in-toto link or layout metadata
verify Verify that the software supply chain of the delivered product
Flags:
-h, --help help for in-toto
Use "in-toto [command] --help" for more information about a command.
```

### key

```text
Key management commands
Usage:
in-toto key [command]
Available Commands:
id Output the key id for a given key
layout Output the key layout for a given key in <KEYID>: <KEYOBJ> format
Flags:
-h, --help help for key
Use "in-toto key [command] --help" for more information about a command.
```

### run

```text
Executes the passed command and records paths and hashes of 'materials' (i.e.
files before command execution) and 'products' (i.e. files after command
execution) and stores them together with other information (executed command,
return value, stdout, stderr, ...) to a link metadata file, which is signed
with the passed key. Returns nonzero value on failure and zero otherwise.
Usage:
in-toto run [flags]
Flags:
-c, --cert string Path to a PEM formatted certificate that corresponds with
the provided key.
-e, --exclude stringArray path patterns to match paths that should not be recorded as 0
‘materials’ or ‘products’. Passed patterns override patterns defined
in environment variables or config files. See Config docs for details.
-h, --help help for run
-k, --key string Path to a PEM formatted private key file used to sign
the resulting link metadata. (passing one of '--key'
or '--gpg' is required)
-l, --lstrip-paths stringArray path prefixes used to left-strip artifact paths before storing
them to the resulting link metadata. If multiple prefixes
are specified, only a single prefix can match the path of
any artifact and that is then left-stripped. All prefixes
are checked to ensure none of them are a left substring
of another.
-m, --materials stringArray Paths to files or directories, whose paths and hashes
are stored in the resulting link metadata before the
command is executed. Symlinks are followed.
-n, --name string Name used to associate the resulting link metadata
with the corresponding step defined in an in-toto
layout.
-d, --metadata-directory string directory to store link metadata (default "./")
-p, --products stringArray Paths to files or directories, whose paths and hashes
are stored in the resulting link metadata after the
command is executed. Symlinks are followed.
-r, --run-dir string runDir specifies the working directory of the command.
If runDir is the empty string, the command will run in the
calling process's current directory. The runDir directory must
exist, be writable, and not be a symlink.
```

### sign

```text
Provides command line interface to sign in-toto link or layout metadata
Usage:
in-toto sign [flags]
Flags:
-f, --file string Path to link or layout file to be signed or verified.
-h, --help help for sign
-k, --key string Path to PEM formatted private key used to sign the passed
root layout's signature(s). Passing exactly one key using
'--layout-key' is required.
-o, --output string Path to store metadata file to be signed
```

### verify

```text
in-toto-verify is the main verification tool of the suite, and
it is used to verify that the software supply chain of the delivered
product was carried out as defined in the passed in-toto supply chain
layout. Evidence for supply chain steps must be available in the form
of link metadata files named ‘<step name>.<functionary keyid prefix>.link’.
Usage:
in-toto verify [flags]
Flags:
-h, --help help for verify
-i, --intermediate-certs strings Path(s) to PEM formatted certificates, used as intermediaries to verify
the chain of trust to the layout's trusted root. These will be used in
addition to any intermediates in the layout.
-l, --layout string Path to root layout specifying the software supply chain to be verified
-k, --layout-keys strings Path(s) to PEM formatted public key(s), used to verify the passed
root layout's signature(s). Passing at least one key using
'--layout-keys' is required. For each passed key the layout
must carry a valid signature.
-d, --link-dir string Path to directory where link metadata files for steps defined in
the root layout should be loaded from. If not passed links are
loaded from the current working directory.
```

### record

```text
Creates a signed link metadata file in two steps, in order to provide
evidence for supply chain steps that cannot be carried out by a single command
(for which ‘in-toto-run’ should be used). It returns a non-zero value on
failure and zero otherwise.
Usage:
in-toto record [command]
Available Commands:
start Creates a preliminary link file recording the paths and hashes of the passed materials and signs it with the passed functionary’s key.
stop Records and adds the paths and hashes of the passed products to the link metadata file and updates the signature.
Flags:
-c, --cert string Path to a PEM formatted certificate that corresponds with the provided key.
-e, --exclude stringArray Path patterns to match paths that should not be recorded as
‘materials’ or ‘products’. Passed patterns override patterns defined
in environment variables or config files. See Config docs for details.
-h, --help help for record
-k, --key string Path to a private key file to sign the resulting link metadata.
The keyid prefix is used as an infix for the link metadata filename,
i.e. ‘<name>.<keyid prefix>.link’. See ‘–key-type’ for available
formats. Passing one of ‘–key’ or ‘–gpg’ is required.
-l, --lstrip-paths stringArray Path prefixes used to left-strip artifact paths before storing
them to the resulting link metadata. If multiple prefixes
are specified, only a single prefix can match the path of
any artifact and that is then left-stripped. All prefixes
are checked to ensure none of them are a left substring
of another.
-d, --metadata-directory string directory to store link metadata (default "./")
-n, --name string name for the resulting link metadata file.
It is also used to associate the link with a step defined
in an in-toto layout.
Use "in-toto record [command] --help" for more information about a command.
```

## Layout Certificate Constraints

Currently the following constraints supported:

```json
{
"cert_constraints": [{
"common_name": "write-code.example.com",
"dns_names": [
""
],
"emails": [
""
],
"organizations": [
"*"
],
"roots": [
"*"
],
"uris": [
"spiffe://example.com/write-code"
]
}, {
"uris": [],
"common_names": ["Some User"]
}]
}
```

## Not (yet) supported

This golang implementation was focused on verification on admission controllers
Expand Down
Loading

0 comments on commit 6b6d786

Please sign in to comment.