Skip to content

Commit

Permalink
Merge pull request #120 from jonnystoten/aws-kms
Browse files Browse the repository at this point in the history
Add support for AWS KMS
  • Loading branch information
jku authored Nov 22, 2023
2 parents df797d1 + d39e916 commit 2c59d61
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Supported features include:
* Guided signing events for distributed signing
* TUF delegations with signature thresholds
* Signing with hardware keys and Sigstore
* Automated online signing (Google Cloud, Azure, Sigstore)
* Automated online signing (Google Cloud, Azure, AWS, Sigstore)
* No custom code required

The optimal use case is TUF repositories with a low to moderate frequency of change, both for artifacts and keys.
Expand Down
27 changes: 21 additions & 6 deletions actions/online-sign/action.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
name: 'Online sign'
description: 'Creates a snapshot and timestamp if needed, moves publish branch if needed'
name: "Online sign"
description: "Creates a snapshot and timestamp if needed, moves publish branch if needed"

inputs:
gcp_workload_identity_provider:
description: 'Google Cloud workload identity provider'
description: "Google Cloud workload identity provider"
required: false
default: ''
default: ""
gcp_service_account:
description: 'Google Cloud service account name'
description: "Google Cloud service account name"
required: false
default: ''
default: ""
aws_region:
description: "AWS region"
required: false
default: ""
aws_role_to_assume:
description: "AWS role to assume"
required: false
default: ""

runs:
using: "composite"
Expand All @@ -26,6 +34,13 @@ runs:
workload_identity_provider: ${{ inputs.gcp_workload_identity_provider }}
service_account: ${{ inputs.gcp_service_account }}

- name: Authenticate to AWS
if: inputs.aws_role_to_assume != ''
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a #v4.0.1
with:
aws-region: ${{ inputs.aws_region }}
role-to-assume: ${{ inputs.aws_role_to_assume }}

- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
with:
python-version: "3.11"
Expand Down
14 changes: 14 additions & 0 deletions docs/ONLINE-SIGNING-SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Currently supported signing methods include
* Sigstore (experimental)
* Google Cloud KMS
* Azure Key Vault
* AWS KMS

## Configuration

Expand Down Expand Up @@ -62,3 +63,16 @@ currently experimental (and not supported by all TUF client libraries)
login](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)
and authenticate against the environment where the key vault
exists. You will need to the role _"Key Vault Crypto User"_).
### AWS KMS
1. Make sure AWS IAM permissions allow your GitHub repositorys OIDC identity to sign with a KMS key.
1. Define your authentication details as repository variables in _Settings->Secrets and variables->Actions->Variables_:
```
AWS_ROLE_TO_ASSUME: arn:aws:iam::175142243308:role/tuf-testing-online-key
AWS_REGION: us-east-1
```
1. _(only needed for initial configuration)_ Prepare your local environment for accessing the cloud KMS:
Use the [AWS CLI](https://aws.amazon.com/cli/) and authenticate in the
environment where you plan to run `tuf-on-ci-delegate` tool (you will need permission to use
the KMS key).
6 changes: 3 additions & 3 deletions docs/REPOSITORY-MAINTENANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ ongoing maintenance.
`publish`
1. Clone the repository locally and [configure your local signing tool](SIGNER-SETUP.md)
1. Choose your online signing method and [configure it](ONLINE-SIGNING-SETUP.md):
* Google Cloud KMS and Azure Key Vault are fully supported
* Google Cloud KMS, Azure Key Vault, and AWS KMS are fully supported
* Sigstore requires no configuration (but is experimental)
1. Run `tuf-on-ci-delegate sign/init` to configure the repository and to start the
first signing event
* The tool prompts for various repository details and finally prompts to
* The tool prompts for various repository details and finally prompts to
sign and push the initial metadata to a signing event branch
1. When this initial signing event branch is merged, the repository generates the
first snapshot and timestamp, and publishes the first repository version
Expand All @@ -31,7 +31,7 @@ Modifying a role is needed when:

Roles are modified with `tuf-on-ci-delegate <event> <role>`.
* The event name can be chosen freely (and will be used as a branch name). If the signing
event does not exist yet, it will be created as a result.
event does not exist yet, it will be created as a result.
* The tool will prompt for new signers and other details, and then prompt to push changes
to the repository.
* The push triggers creation of a signing event GitHub issue. The repository will report the
Expand Down
2 changes: 1 addition & 1 deletion repo/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ version = "0.2.0"
description = "TUF-on-CI repository tools, intended to be executed on a CI system"
readme = "README.md"
dependencies = [
"securesystemslib[azurekms, gcpkms, sigstore, pynacl] ~= 0.30",
"securesystemslib[awskms, azurekms, gcpkms, sigstore, pynacl] ~= 0.30",
"tuf ~= 3.0",
"click ~= 8.1",
]
Expand Down
2 changes: 1 addition & 1 deletion signer/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ version = "0.2.0"
description = "Signing tools for TUF-on-CI"
readme = "README.md"
dependencies = [
"securesystemslib[gcpkms,hsm,sigstore] ~= 0.30",
"securesystemslib[awskms,azurekms,gcpkms,hsm,sigstore] ~= 0.30",
"tuf ~= 3.0",
"click ~= 8.1",
]
Expand Down
37 changes: 36 additions & 1 deletion signer/tuf_on_ci_sign/delegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import click
from securesystemslib.signer import (
KEY_FOR_TYPE_AND_SCHEME,
AWSSigner,
AzureSigner,
GCPSigner,
Key,
Expand Down Expand Up @@ -196,9 +197,10 @@ def _collect_online_key(user_config: User) -> Key:
click.echo(" 1. Sigstore")
click.echo(" 2. Google Cloud KMS")
click.echo(" 3. Azure Key Vault")
click.echo(" 4. AWS KMS")
choice = click.prompt(
bold("Please select online key type"),
type=click.IntRange(1, 4),
type=click.IntRange(0, 4),
default=1,
show_default=True,
)
Expand All @@ -222,6 +224,15 @@ def _collect_online_key(user_config: User) -> Key:
except Exception as e:
raise click.ClickException(f"Failed to read Azure Keyvault key: {e}")
if choice == 4:
key_id = _collect_string("Enter AWS KMS key id")
scheme = _collect_key_scheme()
try:
uri, key = AWSSigner.import_(key_id, scheme)
key.unrecognized_fields["x-tuf-on-ci-online-uri"] = uri
return key
except Exception as e:
raise click.ClickException(f"Failed to read AWS KMS key: {e}")
if choice == 0:
# This could be generic support, but for now it's a hidden test key.
# key value 1d9a024348e413892aeeb8cc8449309c152f48177200ee61a02ae56f450c6480
uri = "envvar:LOCAL_TESTING_KEY"
Expand All @@ -245,6 +256,30 @@ def _collect_string(prompt: str) -> str:
return data


def _collect_key_scheme() -> str:
scheme_choices = {
1: {"ssllib": "ecdsa-sha2-nistp256", "aws": "ECDSA_SHA_256"},
2: {"ssllib": "ecdsa-sha2-nistp384", "aws": "ECDSA_SHA_384"},
3: {"ssllib": "ecdsa-sha2-nistp512", "aws": "ECDSA_SHA_512"},
4: {"ssllib": "rsassa-pss-sha256", "aws": "RSASSA_PSS_SHA_256"},
5: {"ssllib": "rsassa-pss-sha384", "aws": "RSASSA_PSS_SHA_384"},
6: {"ssllib": "rsassa-pss-sha512", "aws": "RSASSA_PSS_SHA_512"},
7: {"ssllib": "rsa-pkcs1v15-sha256", "aws": "RSASSA_PKCS1_V1_5_SHA_256"},
8: {"ssllib": "rsa-pkcs1v15-sha384", "aws": "RSASSA_PKCS1_V1_5_SHA_384"},
9: {"ssllib": "rsa-pkcs1v15-sha512", "aws": "RSASSA_PKCS1_V1_5_SHA_512"},
}

for key, value in scheme_choices.items():
click.echo(f"{key}. {value['aws']}")
choice = click.prompt(
bold("Please select AWS key scheme"),
type=click.IntRange(1, 9),
default=1,
show_default=True,
)
return scheme_choices[choice]["ssllib"]


def _init_repository(repo: SignerRepository) -> bool:
click.echo("Creating a new TUF-on-CI repository")

Expand Down
31 changes: 18 additions & 13 deletions tests/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,21 @@ strip_signatures()
rm "$1e2e"
}

git_clone()
{
REPO=$1
REMOTE=$2
USER_NAME=$3
USER_EMAIL=$4
git -C $REPO clone --quiet $REMOTE . 2>/dev/null
git -C $REPO config user.email "$USER_EMAIL"
git -C $REPO config user.name "$USER_NAME"
git -C $REPO config commit.gpgsign false
}

git_repo()
{
git \
-C $REPO_GIT \
-c user.name=tuf-on-ci \
-c user.email=41898282+github-actions[bot]@users.noreply.github.com \
-c commit.gpgsign=false \
$@
git -C $REPO_GIT "$@"
}

repo_setup()
Expand All @@ -80,7 +87,7 @@ repo_setup()
git -C $UPSTREAM_GIT init --quiet --bare --initial-branch=main

# Clone upstream to repo, create a dummy commit so merges are possible
git_repo clone --quiet $UPSTREAM_GIT . 2>/dev/null
git_clone $REPO_GIT $UPSTREAM_GIT "tuf-on-ci" "41898282+github-actions[bot]@users.noreply.github.com"
touch $REPO_GIT/.dummy $REPO_DIR/out
git_repo add .dummy
git_repo commit -m "init" --quiet
Expand All @@ -100,9 +107,7 @@ signer_setup()
cp -r $SCRIPT_DIR/softhsm/tokens-$USER $SIGNER_DIR/tokens

# clone the test repository
git -C $SIGNER_GIT clone --quiet $UPSTREAM_GIT .
git -C $SIGNER_GIT config user.email "$USER@example.com"
git -C $SIGNER_GIT config user.name "$USER"
git_clone $SIGNER_GIT $UPSTREAM_GIT "$USER@example.com" "$USER"

# Set user configuration
echo -e "[settings]\n" \
Expand All @@ -126,7 +131,7 @@ signer_init()
"" # Configure root ? [enter to continue]
"" # Configure targets? [enter to continue]
"1" # Configure online roles? [1: configure key]
"4" # Enter online key type
"0" # Enter online key type
"" # Configure online roles? [enter to continue]
"2" # Choose signing key [2: yubikey]
"" # Insert HW key and press enter
Expand Down Expand Up @@ -213,7 +218,7 @@ signer_init_shorter_snapshot_expiry()
"" # Configure root ? [enter to continue]
"" # Configure targets? [enter to continue]
"1" # Configure online roles? [1: configure key]
"4" # Enter online key type
"0" # Enter online key type
"3" # Configure online roles? [3: configure snapshot]
"10" # Enter expiry [10 days]
"4" # Enter signing period [4 days]
Expand Down Expand Up @@ -249,7 +254,7 @@ signer_init_multiuser()
"2" # Enter threshold
"" # Configure targets? [enter to continue]
"1" # Configure online roles? [1: configure key]
"4" # Enter online key type
"0" # Enter online key type
"" # Configure online roles? [enter to continue]
"2" # Choose signing key [2: yubikey]
"" # Insert HW key and press enter
Expand Down

0 comments on commit 2c59d61

Please sign in to comment.