Showing preview only (4,777K chars total). Download the full file or copy to clipboard to get everything.
Repository: smallstep/certificates
Branch: master
Commit: 6e8ec6140523
Files: 543
Total size: 4.5 MB
Directory structure:
gitextract_pt61h5ml/
├── .VERSION
├── .dockerignore
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.yml
│ │ ├── config.yml
│ │ ├── documentation-request.md
│ │ └── enhancement.md
│ ├── PULL_REQUEST_TEMPLATE
│ ├── dependabot.yml
│ ├── workflows/
│ │ ├── actionci.yml
│ │ ├── ci.yml
│ │ ├── code-scan-cron.yml
│ │ ├── dependabot-auto-merge.yml
│ │ ├── publish-packages.yml
│ │ ├── release.yml
│ │ └── triage.yml
│ └── zizmor.yml
├── .gitignore
├── .goreleaser.yml
├── .version.sh
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── acme/
│ ├── account.go
│ ├── account_test.go
│ ├── api/
│ │ ├── account.go
│ │ ├── account_test.go
│ │ ├── eab.go
│ │ ├── eab_test.go
│ │ ├── handler.go
│ │ ├── handler_test.go
│ │ ├── middleware.go
│ │ ├── middleware_test.go
│ │ ├── order.go
│ │ ├── order_test.go
│ │ ├── revoke.go
│ │ ├── revoke_test.go
│ │ └── wire_integration_test.go
│ ├── authorization.go
│ ├── authorization_test.go
│ ├── certificate.go
│ ├── challenge.go
│ ├── challenge_test.go
│ ├── challenge_tpmsimulator_test.go
│ ├── challenge_wire_test.go
│ ├── client.go
│ ├── common.go
│ ├── db/
│ │ └── nosql/
│ │ ├── account.go
│ │ ├── account_test.go
│ │ ├── authz.go
│ │ ├── authz_test.go
│ │ ├── certificate.go
│ │ ├── certificate_test.go
│ │ ├── challenge.go
│ │ ├── challenge_test.go
│ │ ├── eab.go
│ │ ├── eab_test.go
│ │ ├── nonce.go
│ │ ├── nonce_test.go
│ │ ├── nosql.go
│ │ ├── nosql_test.go
│ │ ├── order.go
│ │ ├── order_test.go
│ │ ├── wire.go
│ │ └── wire_test.go
│ ├── db.go
│ ├── db_test.go
│ ├── errors.go
│ ├── errors_test.go
│ ├── linker.go
│ ├── linker_test.go
│ ├── nonce.go
│ ├── order.go
│ ├── order_test.go
│ ├── status.go
│ └── wire/
│ ├── id.go
│ └── id_test.go
├── api/
│ ├── api.go
│ ├── api_test.go
│ ├── crl.go
│ ├── crl_test.go
│ ├── log/
│ │ ├── log.go
│ │ └── log_test.go
│ ├── models/
│ │ └── scep.go
│ ├── read/
│ │ ├── read.go
│ │ └── read_test.go
│ ├── rekey.go
│ ├── render/
│ │ ├── render.go
│ │ └── render_test.go
│ ├── renew.go
│ ├── revoke.go
│ ├── revoke_test.go
│ ├── sign.go
│ ├── ssh.go
│ ├── sshRekey.go
│ ├── sshRenew.go
│ ├── sshRevoke.go
│ └── ssh_test.go
├── authority/
│ ├── admin/
│ │ ├── api/
│ │ │ ├── acme.go
│ │ │ ├── acme_test.go
│ │ │ ├── admin.go
│ │ │ ├── admin_test.go
│ │ │ ├── handler.go
│ │ │ ├── middleware.go
│ │ │ ├── middleware_test.go
│ │ │ ├── policy.go
│ │ │ ├── policy_test.go
│ │ │ ├── provisioner.go
│ │ │ ├── provisioner_test.go
│ │ │ ├── webhook.go
│ │ │ └── webhook_test.go
│ │ ├── db/
│ │ │ └── nosql/
│ │ │ ├── admin.go
│ │ │ ├── admin_test.go
│ │ │ ├── nosql.go
│ │ │ ├── policy.go
│ │ │ ├── policy_test.go
│ │ │ ├── provisioner.go
│ │ │ └── provisioner_test.go
│ │ ├── db.go
│ │ └── errors.go
│ ├── administrator/
│ │ └── collection.go
│ ├── admins.go
│ ├── authority.go
│ ├── authority_test.go
│ ├── authorize.go
│ ├── authorize_test.go
│ ├── config/
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── ssh.go
│ │ ├── ssh_test.go
│ │ ├── tls_options.go
│ │ ├── tls_options_test.go
│ │ ├── types.go
│ │ └── types_test.go
│ ├── config.go
│ ├── export.go
│ ├── http_client.go
│ ├── http_client_test.go
│ ├── internal/
│ │ └── constraints/
│ │ ├── constraints.go
│ │ ├── constraints_test.go
│ │ └── verify.go
│ ├── linkedca.go
│ ├── meter.go
│ ├── options.go
│ ├── policy/
│ │ ├── engine.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── policy.go
│ │ └── policy_test.go
│ ├── policy.go
│ ├── policy_test.go
│ ├── poolhttp/
│ │ ├── poolhttp.go
│ │ └── poolhttp_test.go
│ ├── provisioner/
│ │ ├── acme.go
│ │ ├── acme_118_test.go
│ │ ├── acme_119_test.go
│ │ ├── acme_test.go
│ │ ├── aws.go
│ │ ├── aws_certificates.pem
│ │ ├── aws_test.go
│ │ ├── azure.go
│ │ ├── azure_test.go
│ │ ├── claims.go
│ │ ├── claims_test.go
│ │ ├── collection.go
│ │ ├── collection_test.go
│ │ ├── controller.go
│ │ ├── controller_test.go
│ │ ├── duration.go
│ │ ├── duration_test.go
│ │ ├── extension.go
│ │ ├── extension_test.go
│ │ ├── gcp/
│ │ │ ├── projectvalidator.go
│ │ │ └── projectvalidator_test.go
│ │ ├── gcp.go
│ │ ├── gcp_test.go
│ │ ├── jwk.go
│ │ ├── jwk_test.go
│ │ ├── k8sSA.go
│ │ ├── k8sSA_test.go
│ │ ├── keystore.go
│ │ ├── keystore_test.go
│ │ ├── method.go
│ │ ├── nebula.go
│ │ ├── nebula_test.go
│ │ ├── noop.go
│ │ ├── noop_test.go
│ │ ├── oidc.go
│ │ ├── oidc_test.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── policy.go
│ │ ├── provisioner.go
│ │ ├── provisioner_test.go
│ │ ├── scep.go
│ │ ├── scep_test.go
│ │ ├── sign_options.go
│ │ ├── sign_options_test.go
│ │ ├── sign_ssh_options.go
│ │ ├── sign_ssh_options_test.go
│ │ ├── ssh_options.go
│ │ ├── ssh_options_test.go
│ │ ├── ssh_test.go
│ │ ├── sshpop.go
│ │ ├── sshpop_test.go
│ │ ├── testdata/
│ │ │ ├── certs/
│ │ │ │ ├── apple-att-ca.crt
│ │ │ │ ├── aws-test.crt
│ │ │ │ ├── aws.crt
│ │ │ │ ├── bad-extension.crt
│ │ │ │ ├── bar.pub
│ │ │ │ ├── ecdsa.csr
│ │ │ │ ├── ed25519.csr
│ │ │ │ ├── foo.crt
│ │ │ │ ├── foo.pub
│ │ │ │ ├── good-extension.crt
│ │ │ │ ├── root_ca.crt
│ │ │ │ ├── rsa.csr
│ │ │ │ ├── short-rsa.csr
│ │ │ │ ├── ssh_host_ca_key.pub
│ │ │ │ ├── ssh_user_ca_key.pub
│ │ │ │ ├── x5c-leaf.crt
│ │ │ │ └── yubico-piv-ca.crt
│ │ │ ├── secrets/
│ │ │ │ ├── bar.priv
│ │ │ │ ├── bar_host_ssh_key
│ │ │ │ ├── ecdsa.key
│ │ │ │ ├── ed25519.key
│ │ │ │ ├── foo.key
│ │ │ │ ├── foo.priv
│ │ │ │ ├── foo_user_ssh_key
│ │ │ │ ├── rsa.key
│ │ │ │ ├── ssh_host_ca_key
│ │ │ │ ├── ssh_user_ca_key
│ │ │ │ └── x5c-leaf.key
│ │ │ └── templates/
│ │ │ └── cr.tpl
│ │ ├── timeduration.go
│ │ ├── timeduration_test.go
│ │ ├── utils_test.go
│ │ ├── webhook.go
│ │ ├── webhook_test.go
│ │ ├── wire/
│ │ │ ├── dpop_options.go
│ │ │ ├── dpop_options_test.go
│ │ │ ├── oidc_options.go
│ │ │ ├── oidc_options_test.go
│ │ │ ├── wire_options.go
│ │ │ └── wire_options_test.go
│ │ ├── x5c.go
│ │ └── x5c_test.go
│ ├── provisioners.go
│ ├── provisioners_test.go
│ ├── root.go
│ ├── root_test.go
│ ├── ssh.go
│ ├── ssh_test.go
│ ├── testdata/
│ │ ├── certs/
│ │ │ ├── badsig.csr
│ │ │ ├── foo.crt
│ │ │ ├── foo.csr
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── provisioner-not-found.crt
│ │ │ ├── renew-disabled.crt
│ │ │ ├── root_ca.crt
│ │ │ ├── ssh_host_ca_key.pub
│ │ │ └── ssh_user_ca_key.pub
│ │ ├── scep/
│ │ │ ├── intermediate.crt
│ │ │ ├── intermediate.key
│ │ │ ├── root.crt
│ │ │ └── root.key
│ │ ├── secrets/
│ │ │ ├── foo.key
│ │ │ ├── intermediate_ca_key
│ │ │ ├── max_priv.jwk
│ │ │ ├── max_pub.jwk
│ │ │ ├── provisioner-not-found.key
│ │ │ ├── renew-disabled.key
│ │ │ ├── ssh_host_ca_key
│ │ │ ├── ssh_user_ca_key
│ │ │ ├── step_cli_key
│ │ │ ├── step_cli_key.public
│ │ │ ├── step_cli_key_priv.jwk
│ │ │ └── step_cli_key_pub.jwk
│ │ └── templates/
│ │ ├── badjsonsyntax.tpl
│ │ ├── badjsonvalue.tpl
│ │ ├── ca.tpl
│ │ ├── config.tpl
│ │ ├── error.tpl
│ │ ├── fail.tpl
│ │ ├── include.tpl
│ │ ├── known_hosts.tpl
│ │ ├── sshd_config.tpl
│ │ └── step_includes.tpl
│ ├── tls.go
│ ├── tls_test.go
│ ├── version.go
│ ├── webhook.go
│ └── webhook_test.go
├── autocert/
│ └── README.md
├── ca/
│ ├── acmeClient.go
│ ├── acmeClient_test.go
│ ├── adminClient.go
│ ├── bootstrap.go
│ ├── bootstrap_test.go
│ ├── ca.go
│ ├── ca_test.go
│ ├── client/
│ │ └── requestid.go
│ ├── client.go
│ ├── client_test.go
│ ├── identity/
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── identity.go
│ │ ├── identity_test.go
│ │ └── testdata/
│ │ ├── certs/
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── root_ca.crt
│ │ │ └── server.crt
│ │ ├── config/
│ │ │ ├── badIdentity.json
│ │ │ ├── badca.json
│ │ │ ├── badroot.json
│ │ │ ├── ca.json
│ │ │ ├── defaults.json
│ │ │ ├── fail.json
│ │ │ ├── identity.json
│ │ │ └── tunnel.json
│ │ ├── identity/
│ │ │ ├── expired.crt
│ │ │ ├── identity.crt
│ │ │ ├── identity_key
│ │ │ └── not_before.crt
│ │ └── secrets/
│ │ ├── intermediate_ca_key
│ │ ├── root_ca_key
│ │ └── server_key
│ ├── mutable_tls_config.go
│ ├── provisioner.go
│ ├── provisioner_test.go
│ ├── renew.go
│ ├── signal.go
│ ├── testdata/
│ │ ├── ca.json
│ │ ├── federated-ca.json
│ │ ├── rotate-ca-0.json
│ │ ├── rotate-ca-1.json
│ │ ├── rotate-ca-2.json
│ │ ├── rotate-ca-3.json
│ │ ├── rotated/
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── intermediate_ca_key
│ │ │ ├── root_ca.crt
│ │ │ └── root_ca_key
│ │ ├── rsaca.json
│ │ └── secrets/
│ │ ├── federated_ca.crt
│ │ ├── intermediate_ca.crt
│ │ ├── intermediate_ca_key
│ │ ├── ott_key
│ │ ├── ott_key.public
│ │ ├── ott_mariano_priv.jwk
│ │ ├── ott_mariano_pub.jwk
│ │ ├── root_ca.crt
│ │ ├── root_ca_key
│ │ ├── rsa_intermediate_ca.crt
│ │ ├── rsa_intermediate_ca_key
│ │ ├── rsa_root_ca.crt
│ │ ├── rsa_root_ca_key
│ │ ├── step_cli_key
│ │ ├── step_cli_key.public
│ │ ├── step_cli_key_priv.jwk
│ │ └── step_cli_key_pub.jwk
│ ├── tls.go
│ ├── tls_options.go
│ ├── tls_options_test.go
│ └── tls_test.go
├── cas/
│ ├── apiv1/
│ │ ├── extension.go
│ │ ├── extension_test.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── registry.go
│ │ ├── registry_test.go
│ │ ├── requests.go
│ │ ├── services.go
│ │ └── services_test.go
│ ├── cas.go
│ ├── cas_test.go
│ ├── cloudcas/
│ │ ├── certificate.go
│ │ ├── certificate_test.go
│ │ ├── cloudcas.go
│ │ ├── cloudcas_test.go
│ │ ├── mock_client_test.go
│ │ └── mock_operation_server_test.go
│ ├── softcas/
│ │ ├── softcas.go
│ │ └── softcas_test.go
│ ├── stepcas/
│ │ ├── issuer.go
│ │ ├── issuer_test.go
│ │ ├── jwk_issuer.go
│ │ ├── jwk_issuer_test.go
│ │ ├── stepcas.go
│ │ ├── stepcas_test.go
│ │ ├── x5c_issuer.go
│ │ └── x5c_issuer_test.go
│ └── vaultcas/
│ ├── auth/
│ │ ├── approle/
│ │ │ ├── approle.go
│ │ │ └── approle_test.go
│ │ ├── aws/
│ │ │ ├── aws.go
│ │ │ └── aws_test.go
│ │ └── kubernetes/
│ │ ├── kubernetes.go
│ │ ├── kubernetes_test.go
│ │ └── token
│ ├── vaultcas.go
│ └── vaultcas_test.go
├── cmd/
│ └── step-ca/
│ └── main.go
├── commands/
│ ├── app.go
│ ├── export.go
│ └── onboard.go
├── cosign.pub
├── db/
│ ├── db.go
│ ├── db_test.go
│ ├── simple.go
│ └── simple_test.go
├── debian/
│ └── copyright
├── docker/
│ ├── Dockerfile
│ ├── Dockerfile.hsm
│ └── entrypoint.sh
├── errs/
│ ├── error.go
│ └── errors_test.go
├── examples/
│ ├── README.md
│ ├── ansible/
│ │ ├── smallstep-certs/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── smallstep-install/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ └── smallstep-ssh/
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ └── tasks/
│ │ └── main.yml
│ ├── basic-client/
│ │ └── client.go
│ ├── basic-federation/
│ │ ├── client/
│ │ │ └── main.go
│ │ ├── pki/
│ │ │ ├── cloud/
│ │ │ │ ├── certs/
│ │ │ │ │ ├── intermediate_ca.crt
│ │ │ │ │ ├── kubernetes_root_ca.crt
│ │ │ │ │ └── root_ca.crt
│ │ │ │ ├── config/
│ │ │ │ │ ├── ca.federated.json
│ │ │ │ │ └── ca.json
│ │ │ │ └── secrets/
│ │ │ │ ├── intermediate_ca_key
│ │ │ │ └── root_ca_key
│ │ │ └── kubernetes/
│ │ │ ├── certs/
│ │ │ │ ├── cloud_root_ca.crt
│ │ │ │ ├── intermediate_ca.crt
│ │ │ │ └── root_ca.crt
│ │ │ ├── config/
│ │ │ │ ├── ca.federated.json
│ │ │ │ └── ca.json
│ │ │ └── secrets/
│ │ │ ├── intermediate_ca_key
│ │ │ └── root_ca_key
│ │ └── server/
│ │ └── main.go
│ ├── bootstrap-client/
│ │ └── client.go
│ ├── bootstrap-mtls-server/
│ │ └── server.go
│ ├── bootstrap-tls-server/
│ │ └── server.go
│ ├── docker/
│ │ ├── Makefile
│ │ ├── ca/
│ │ │ ├── Dockerfile
│ │ │ └── pki/
│ │ │ ├── config/
│ │ │ │ └── ca.json
│ │ │ └── secrets/
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── intermediate_ca_key
│ │ │ ├── root_ca.crt
│ │ │ └── root_ca_key
│ │ ├── docker-compose.yml
│ │ ├── nginx/
│ │ │ ├── Dockerfile
│ │ │ ├── certwatch.sh
│ │ │ ├── entrypoint.sh
│ │ │ └── site.conf
│ │ ├── password.txt
│ │ └── renewer/
│ │ ├── Dockerfile
│ │ ├── crontab
│ │ └── entrypoint.sh
│ ├── pki/
│ │ ├── config/
│ │ │ └── ca.json
│ │ └── secrets/
│ │ ├── intermediate_ca.crt
│ │ ├── intermediate_ca_key
│ │ ├── root_ca.crt
│ │ └── root_ca_key
│ └── puppet/
│ ├── ca.json.erb
│ ├── defaults.json.erb
│ ├── step.pp
│ ├── step_ca.pp
│ └── tls_server.pp
├── go.mod
├── go.sum
├── internal/
│ ├── cast/
│ │ ├── cast.go
│ │ └── cast_test.go
│ ├── httptransport/
│ │ └── httptransport.go
│ ├── metrix/
│ │ └── meter.go
│ └── userid/
│ └── userid.go
├── logging/
│ ├── clf.go
│ ├── handler.go
│ ├── handler_test.go
│ ├── logger.go
│ └── responselogger.go
├── middleware/
│ └── requestid/
│ ├── requestid.go
│ └── requestid_test.go
├── monitoring/
│ └── monitoring.go
├── pki/
│ ├── helm.go
│ ├── helm_test.go
│ ├── pki.go
│ ├── pki_test.go
│ ├── templates.go
│ └── testdata/
│ └── helm/
│ ├── simple.yml
│ ├── with-acme-and-duplicate-provisioner-name.yml
│ ├── with-acme.yml
│ ├── with-admin.yml
│ ├── with-provisioner.yml
│ ├── with-ssh-and-acme.yml
│ ├── with-ssh-and-duplicate-provisioner-name.yml
│ └── with-ssh.yml
├── policy/
│ ├── engine.go
│ ├── engine_test.go
│ ├── options.go
│ ├── options_test.go
│ ├── ssh.go
│ ├── validate.go
│ └── x509.go
├── scep/
│ ├── api/
│ │ ├── api.go
│ │ └── api_test.go
│ ├── authority.go
│ ├── authority_test.go
│ ├── options.go
│ ├── provisioner.go
│ └── scep.go
├── scripts/
│ ├── README.md
│ ├── badger-migration/
│ │ └── main.go
│ ├── install-step-ra.sh
│ ├── package-repo-import.sh
│ └── package-upload.sh
├── server/
│ └── server.go
├── systemd/
│ ├── README.md
│ └── step-ca.service
├── templates/
│ ├── templates.go
│ ├── templates_test.go
│ ├── values.go
│ └── values_test.go
├── test/
│ └── integration/
│ ├── requestid_test.go
│ └── scep/
│ ├── common_test.go
│ ├── decrypter_cas_test.go
│ ├── decrypter_test.go
│ ├── internal/
│ │ └── x509/
│ │ ├── debug.go
│ │ ├── doc.go
│ │ ├── oid.go
│ │ ├── parser.go
│ │ ├── pkcs1.go
│ │ ├── verify.go
│ │ └── x509.go
│ ├── regular_cas_test.go
│ ├── regular_test.go
│ ├── windows_go1.23_test.go
│ └── windows_test.go
├── tools.go
└── webhook/
├── options.go
├── options_test.go
└── types.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .VERSION
================================================
$Format:%d$
================================================
FILE: .dockerignore
================================================
bin
coverage.txt
*.test
*.out
.travis-releases
================================================
FILE: .gitattributes
================================================
.VERSION export-subst
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: Bug Report
description: File a bug report
title: "[Bug]: "
labels: ["bug", "needs triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: steps
attributes:
label: Steps to Reproduce
description: Tell us how to reproduce this issue.
placeholder: These are the steps!
validations:
required: true
- type: textarea
id: your-env
attributes:
label: Your Environment
value: |-
* OS -
* `step-ca` Version -
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: What did you expect to happen?
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: Actual Behavior
description: What happens instead?
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional Context
description: Add any other context about the problem here.
validations:
required: false
- type: textarea
id: contributing
attributes:
label: Contributing
value: |
Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).
validations:
required: false
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
- name: Ask on Discord
url: https://discord.gg/7xgjhVAg6g
about: You can ask for help here!
- name: Want to contribute to step certificates?
url: https://github.com/smallstep/certificates/blob/master/CONTRIBUTING.md
about: Be sure to read contributing guidelines!
================================================
FILE: .github/ISSUE_TEMPLATE/documentation-request.md
================================================
---
name: Documentation Request
about: Request documentation for a feature
title: '[Docs]:'
labels: docs, needs triage
assignees: ''
---
## Hello!
<!-- Please leave this section as-is, it's designed to help others in the community know how to interact with our GitHub issues. -->
- Vote on this issue by adding a 👍 reaction
- If you want to document this feature, comment to let us know (we'll work with you on design, scheduling, etc.)
## Affected area/feature
<!---
Tell us which feature you'd like to see documented.
- Where would you like that documentation to live (command line usage output, website, github markdown on the repo)?
- If there are specific attributes or options you'd like to see documented, please include those in the request.
-->
================================================
FILE: .github/ISSUE_TEMPLATE/enhancement.md
================================================
---
name: Enhancement
about: Suggest an enhancement to step-ca
title: ''
labels: enhancement, needs triage
assignees: ''
---
## Hello!
<!-- Please leave this section as-is,
it's designed to help others in the community know how to interact with our GitHub issues. -->
- Vote on this issue by adding a 👍 reaction
- If you want to implement this feature, comment to let us know (we'll work with you on design, scheduling, etc.)
## Issue details
<!-- Enhancement requests are most helpful when they describe the problem you're having
as well as articulating the potential solution you'd like to see built. -->
## Why is this needed?
<!-- Let us know why you think this enhancement would be good for the project or community. -->
================================================
FILE: .github/PULL_REQUEST_TEMPLATE
================================================
<!---
Please provide answers in the spaces below each prompt, where applicable.
Not every PR requires responses for each prompt.
Use your discretion.
-->
#### Name of feature:
#### Pain or issue this feature alleviates:
#### Why is this important to the project (if not answered above):
#### Is there documentation on how to use this feature? If so, where?
#### In what environments or workflows is this feature supported?
#### In what environments or workflows is this feature explicitly NOT supported (if any)?
#### Supporting links/other PRs/issues:
💔Thank you!
================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
================================================
FILE: .github/workflows/actionci.yml
================================================
name: Action CI
on:
push:
tags-ignore:
- 'v*'
branches:
- "master"
pull_request:
workflow_call:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
actionci:
permissions:
contents: read
security-events: write
uses: smallstep/workflows/.github/workflows/actionci.yml@main
with:
zizmor-advanced-security: true
secrets: inherit
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
tags-ignore:
- 'v*'
branches:
- "master"
pull_request:
workflow_call:
secrets:
CODECOV_TOKEN:
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
ci:
permissions:
actions: read
contents: read
security-events: write
uses: smallstep/workflows/.github/workflows/goCI.yml@main
with:
only-latest-golang: false
os-dependencies: 'libpcsclite-dev'
run-codeql: true
test-command: 'V=1 make test'
secrets: inherit
================================================
FILE: .github/workflows/code-scan-cron.yml
================================================
on:
schedule:
- cron: '0 0 * * *'
permissions:
actions: read
contents: read
security-events: write
jobs:
code-scan:
uses: smallstep/workflows/.github/workflows/code-scan.yml@main
================================================
FILE: .github/workflows/dependabot-auto-merge.yml
================================================
name: Dependabot auto-merge
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot-auto-merge:
uses: smallstep/workflows/.github/workflows/dependabot-auto-merge.yml@main
secrets: inherit
================================================
FILE: .github/workflows/publish-packages.yml
================================================
name: Publish to packages.smallstep.com
# Independently publish packages to Red Hat (RPM) and Debian (DEB) repositories
# without running a full release. Downloads packages from GitHub releases,
# uploads to GCS, and imports to Artifact Registry.
#
# Usage (CLI):
# gh workflow run publish-packages.yml -f tag=v0.28.0
on:
workflow_dispatch:
inputs:
tag:
description: 'Git tag to publish (e.g., v0.28.0)'
required: true
type: string
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.tag }}
fetch-depth: 0
- name: Extract version
id: version
run: echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
env:
TAG: ${{ inputs.tag }}
- name: Is Pre-release
id: is_prerelease
run: |
if [[ "$TAG" == *"-rc"* ]]; then
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
else
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
fi
env:
TAG: ${{ inputs.tag }}
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
workload_identity_provider: ${{ secrets.GOOGLE_CLOUD_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.GOOGLE_CLOUD_GITHUB_SERVICE_ACCOUNT }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
with:
project_id: ${{ secrets.GOOGLE_CLOUD_PACKAGES_PROJECT_ID }}
- name: Download packages from GitHub release
run: |
mkdir -p dist
gh release download "$TAG" --pattern "*${VERSION}*.deb" --pattern "*${VERSION}*.rpm" --dir dist
env:
TAG: ${{ inputs.tag }}
VERSION: ${{ steps.version.outputs.version }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload packages to GCS
run: |
for pkg in dist/*.deb dist/*.rpm; do
./scripts/package-upload.sh "$pkg" step-ca ${{ steps.version.outputs.version }}
done
- name: Import packages to Artifact Registry
run: ./scripts/package-repo-import.sh step-ca ${{ steps.version.outputs.version }}
env:
IS_PRERELEASE: ${{ steps.is_prerelease.outputs.is_prerelease }}
================================================
FILE: .github/workflows/release.yml
================================================
name: Create Release & Upload Assets
on:
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
permissions:
contents: write
jobs:
ci:
permissions:
contents: read
actions: read
security-events: write
uses: smallstep/certificates/.github/workflows/ci.yml@master
secrets: inherit
create_release:
name: Create Release
permissions:
contents: write
needs: ci
runs-on: ubuntu-latest
env:
DOCKER_IMAGE: smallstep/step-ca
outputs:
version: ${{ steps.extract-tag.outputs.VERSION }}
is_prerelease: ${{ steps.is_prerelease.outputs.IS_PRERELEASE }}
docker_tags: ${{ env.DOCKER_TAGS }}
docker_tags_hsm: ${{ env.DOCKER_TAGS_HSM }}
steps:
- name: Is Pre-release
id: is_prerelease
env:
REF: ${{ github.ref }}
run: |
set +e
echo "${REF}" | grep "\-rc.*"
OUT=$?
if [ $OUT -eq 0 ]; then IS_PRERELEASE=true; else IS_PRERELEASE=false; fi
echo "IS_PRERELEASE=${IS_PRERELEASE}" >> "${GITHUB_OUTPUT}"
- name: Extract Tag Names
id: extract-tag
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "VERSION=${VERSION}" >> "${GITHUB_OUTPUT}"
echo "DOCKER_TAGS=${{ env.DOCKER_IMAGE }}:${VERSION}" >> "${GITHUB_ENV}"
echo "DOCKER_TAGS_HSM=${{ env.DOCKER_IMAGE }}:${VERSION}-hsm" >> "${GITHUB_ENV}"
- name: Add Latest Tag
if: steps.is_prerelease.outputs.IS_PRERELEASE == 'false'
run: |
echo "DOCKER_TAGS=${{ env.DOCKER_TAGS }},${{ env.DOCKER_IMAGE }}:latest" >> "${GITHUB_ENV}"
echo "DOCKER_TAGS_HSM=${{ env.DOCKER_TAGS_HSM }},${{ env.DOCKER_IMAGE }}:hsm" >> "${GITHUB_ENV}"
- name: Create Release
id: create_release
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
draft: false
prerelease: ${{ steps.is_prerelease.outputs.IS_PRERELEASE }}
goreleaser:
needs: create_release
permissions:
id-token: write
contents: write
packages: write
uses: smallstep/workflows/.github/workflows/goreleaser.yml@main
with:
enable-packages-upload: true
is-prerelease: ${{ needs.create_release.outputs.is_prerelease == 'true' }}
secrets: inherit
build_upload_docker:
name: Build & Upload Docker Images
needs: create_release
permissions:
id-token: write
contents: write
uses: smallstep/workflows/.github/workflows/docker-buildx-push.yml@main
with:
platforms: linux/amd64,linux/386,linux/arm,linux/arm64
tags: ${{ needs.create_release.outputs.docker_tags }}
docker_image: smallstep/step-ca
docker_file: docker/Dockerfile
secrets: inherit
build_upload_docker_hsm:
name: Build & Upload HSM Enabled Docker Images
needs: create_release
permissions:
id-token: write
contents: write
uses: smallstep/workflows/.github/workflows/docker-buildx-push.yml@main
with:
platforms: linux/amd64,linux/386,linux/arm,linux/arm64
tags: ${{ needs.create_release.outputs.docker_tags_hsm }}
docker_image: smallstep/step-ca
docker_file: docker/Dockerfile.hsm
secrets: inherit
================================================
FILE: .github/workflows/triage.yml
================================================
name: Add Issues and PRs to Triage
on:
issues:
types:
- opened
- reopened
pull_request_target:
types:
- opened
- reopened
permissions:
pull-requests: write
issues: write
jobs:
triage:
uses: smallstep/workflows/.github/workflows/triage.yml@main
secrets: inherit
================================================
FILE: .github/zizmor.yml
================================================
rules:
unpinned-uses:
config:
policies:
"smallstep/*": ref-pin
secrets-inherit:
disable: true
ref-confusion:
disable: true
dangerous-triggers:
ignore:
- triage.yml
================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
/bin
*.exe
*.exe~
*.dll
*.so
*.dylib
# Go Workspaces
go.work
go.work.sum
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Others
*.swp
.releases
coverage.txt
output
vendor
dist/
.idea
.envrc
# Packages files
0x889B19391F774443-Certify.key
gha-creds-*.json
================================================
FILE: .goreleaser.yml
================================================
# Documentation: https://goreleaser.com/customization/
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
project_name: step-ca
version: 2
variables:
packageName: step-ca
packageRelease: 1 # Manually update release: in the nfpm section to match this value if you change this
before:
hooks:
# You may remove this if you don't use go modules.
- go mod download
after:
hooks:
# This script depends on IS_PRERELEASE env being set. This is set by CI in the Is Pre-release step.
- cmd: bash scripts/package-repo-import.sh {{ .Var.packageName }} {{ .Version }}
output: true
builds:
-
id: step-ca
env:
- CGO_ENABLED=0
targets:
- darwin_amd64
- darwin_arm64
- freebsd_amd64
- linux_386
- linux_amd64
- linux_arm64
- linux_arm_5
- linux_arm_6
- linux_arm_7
- windows_amd64
flags:
- -trimpath
main: ./cmd/step-ca/main.go
binary: step-ca
ldflags:
- -w -X main.Version={{.Version}} -X main.BuildTime={{.Date}}
archives:
- &ARCHIVE
# Can be used to change the archive formats for specific GOOSs.
# Most common use case is to archive as zip on Windows.
# Default is empty.
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Version }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
format_overrides:
- goos: windows
format: zip
files:
- README.md
- LICENSE
allow_different_binary_count: true
-
<< : *ARCHIVE
id: unversioned
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
wrap_in_directory: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
nfpms:
# Configure nFPM for .deb and .rpm releases
#
# See https://nfpm.goreleaser.com/configuration/
# and https://goreleaser.com/customization/nfpm/
#
# Useful tools for debugging .debs:
# List file contents: dpkg -c dist/step_...deb
# Package metadata: dpkg --info dist/step_....deb
#
- &NFPM
id: packages
builds:
- step-ca
package_name: "{{ .Var.packageName }}"
release: "1"
file_name_template: >-
{{- trimsuffix .ConventionalFileName .ConventionalExtension -}}
{{- if and (eq .Arm "6") (eq .ConventionalExtension ".deb") }}6{{ end -}}
{{- if not (eq .Amd64 "v1")}}{{ .Amd64 }}{{ end -}}
{{- .ConventionalExtension -}}
vendor: Smallstep Labs
homepage: https://github.com/smallstep/certificates
maintainer: Smallstep <techadmin@smallstep.com>
description: >
step-ca is an online certificate authority for secure, automated certificate management.
license: Apache 2.0
section: utils
formats:
- deb
- rpm
priority: optional
bindir: /usr/bin
contents:
- src: debian/copyright
dst: /usr/share/doc/step-ca/copyright
rpm:
signature:
key_file: "{{ .Env.GPG_PRIVATE_KEY_FILE }}"
deb:
signature:
key_file: "{{ .Env.GPG_PRIVATE_KEY_FILE }}"
type: origin
-
<< : *NFPM
id: unversioned
file_name_template: "{{ .PackageName }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
source:
enabled: true
name_template: '{{ .ProjectName }}_{{ .Version }}'
checksum:
name_template: 'checksums.txt'
extra_files:
- glob: ./.releases/*
signs:
- cmd: cosign
signature: "${artifact}.sigstore.json"
args:
- "sign-blob"
- "--bundle=${signature}"
- "${artifact}"
- "--yes"
artifacts: all
publishers:
- name: Google Cloud Artifact Registry
ids:
- packages
cmd: ./scripts/package-upload.sh {{ abs .ArtifactPath }} {{ .Var.packageName }} {{ .Version }} {{ .Var.packageRelease }}
snapshot:
name_template: "{{ .Tag }}-next"
release:
# Repo in which the release will be created.
# Default is extracted from the origin remote URL or empty if its private hosted.
# Note: it can only be one: either github, gitlab or gitea
github:
owner: smallstep
name: certificates
# IDs of the archives to use.
# Defaults to all.
#ids:
# - foo
# - bar
# If set to true, will not auto-publish the release.
# Default is false.
draft: false
# If set to auto, will mark the release as not ready for production
# in case there is an indicator for this in the tag e.g. v1.0.0-rc1
# If set to true, will mark the release as not ready for production.
# Default is false.
prerelease: auto
# You can change the name of the release.
# Default is `{{.Tag}}`
name_template: "Step CA {{ .Tag }} ({{ .Env.RELEASE_DATE }})"
# Header template for the release body.
# Defaults to empty.
header: |
## Official Release Artifacts
#### Linux
- 📦 [step-ca_linux_{{ .Version }}_amd64.tar.gz](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_linux_{{ .Version }}_amd64.tar.gz)
- 📦 [step-ca_{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}_amd64.deb](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}_amd64.deb)
- 📦 [step-ca-{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}.x86_64.rpm](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca-{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}.x86_64.rpm)
- 📦 [step-ca_{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}_arm64.deb](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}_arm64.deb)
- 📦 [step-ca-{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}.aarch64.rpm](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca-{{ replace .Version "-" "." }}-{{ .Var.packageRelease }}.aarch64.rpm)
#### OSX Darwin
- 📦 [step-ca_darwin_{{ .Version }}_amd64.tar.gz](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_darwin_{{ .Version }}_amd64.tar.gz)
- 📦 [step-ca_darwin_{{ .Version }}_arm64.tar.gz](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_darwin_{{ .Version }}_arm64.tar.gz)
#### Windows
- 📦 [step-ca_windows_{{ .Version }}_amd64.zip](https://dl.smallstep.com/gh-release/certificates/gh-release-header/{{ .Tag }}/step-ca_windows_{{ .Version }}_amd64.zip)
For more builds across platforms and architectures, see the `Assets` section below.
And for packaged versions (Docker, k8s, Homebrew), see our [installation docs](https://smallstep.com/docs/step-ca/installation).
Don't see the artifact you need? Open an issue [here](https://github.com/smallstep/certificates/issues/new/choose).
## Signatures and Checksums
`step-ca` uses [sigstore/cosign](https://github.com/sigstore/cosign) for signing and verifying release artifacts.
Below is an example using `cosign` to verify a release artifact:
```
cosign verify-blob \
--bundle step-ca_darwin_{{ .Version }}_amd64.tar.gz.sigstore.json \
--certificate-identity-regexp "https://github\.com/smallstep/workflows/.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
step-ca_darwin_{{ .Version }}_amd64.tar.gz
```
The `checksums.txt` file (in the `Assets` section below) contains a checksum for every artifact in the release.
# Footer template for the release body.
# Defaults to empty.
footer: |
## Thanks!
Those were the changes on {{ .Tag }}!
Come join us on [Discord](https://discord.gg/X2RKGwEbV9) to ask questions, chat about PKI, or get a sneak peek at the freshest PKI memes.
# You can disable this pipe in order to not upload any artifacts.
# Defaults to false.
#disable: true
# You can add extra pre-existing files to the release.
# The filename on the release will be the last part of the path (base). If
# another file with the same name exists, the latest one found will be used.
# Defaults to empty.
extra_files:
- glob: ./.releases/*
#extra_files:
# - glob: ./path/to/file.txt
# - glob: ./glob/**/to/**/file/**/*
# - glob: ./glob/foo/to/bar/file/foobar/override_from_previous
winget:
-
# IDs of the archives to use.
# Empty means all IDs.
ids: [ default ]
#
# Default: ProjectName
# Templates: allowed
name: step-ca
# Publisher name.
#
# Templates: allowed
# Required.
publisher: Smallstep
# Your app's description.
#
# Templates: allowed
# Required.
short_description: "A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management."
# Package identifier.
#
# Default: Publisher.ProjectName
# Templates: allowed
package_identifier: Smallstep.step-ca
# License name.
#
# Templates: allowed
# Required.
license: "Apache-2.0"
# Publisher URL.
#
# Templates: allowed
publisher_url: "https://smallstep.com"
# Publisher support URL.
#
# Templates: allowed
publisher_support_url: "https://github.com/smallstep/certificates/discussions"
# Privacy URL.
#
# Templates: allowed
privacy_url: "https://smallstep.com/privacy-policy/"
# URL which is determined by the given Token (github, gitlab or gitea).
#
# Default depends on the client.
# Templates: allowed
url_template: "https://github.com/smallstep/certificates/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
# Git author used to commit to the repository.
commit_author:
name: goreleaserbot
email: goreleaser@smallstep.com
# The project name and current git tag are used in the format string.
#
# Templates: allowed
commit_msg_template: "{{ .PackageIdentifier }}: {{ .Tag }}"
# Your app's homepage.
homepage: "https://github.com/smallstep/certificates"
# Your app's long description.
#
# Templates: allowed
description: "step-ca is an online certificate authority for secure, automated certificate management. It issues X.509 and SSH certificates using protocols like ACME, OIDC, and SCEP."
# License URL.
#
# Templates: allowed
license_url: "https://github.com/smallstep/certificates/blob/master/LICENSE"
# Release notes.
#
# Templates: allowed
release_notes: "{{.Changelog}}"
# Release notes URL.
#
# Templates: allowed
release_notes_url: "https://github.com/smallstep/certificates/releases/tag/{{ .Tag }}"
# Installation notes.
#
# Templates: allowed
installation_notes: "After installation, run 'step-ca --help' to get started. Documentation: https://smallstep.com/docs/step-ca"
# Create the PR - for testing
skip_upload: auto
# Tags.
tags:
- certificates
- smallstep
- tls
# Repository to push the generated files to.
repository:
owner: smallstep
name: winget-pkgs
branch: "step-ca-{{.Version}}"
# Optionally a token can be provided, if it differs from the token
# provided to GoReleaser
# Templates: allowed
#token: "{{ .Env.GITHUB_PERSONAL_AUTH_TOKEN }}"
# Sets up pull request creation instead of just pushing to the given branch.
# Make sure the 'branch' property is different from base before enabling
# it.
#
# Since: v1.17
pull_request:
# Whether to enable it or not.
enabled: true
check_boxes: true
# Whether to open the PR as a draft or not.
#
# Default: false
# Since: v1.19
# draft: true
# Base can also be another repository, in which case the owner and name
# above will be used as HEAD, allowing cross-repository pull requests.
#
# Since: v1.19
base:
owner: microsoft
name: winget-pkgs
branch: master
scoops:
-
ids: [ default ]
# Template for the url which is determined by the given Token (github or gitlab)
# Default for github is "https://github.com/<repo_owner>/<repo_name>/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
# Default for gitlab is "https://gitlab.com/<repo_owner>/<repo_name>/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}"
# Default for gitea is "https://gitea.com/<repo_owner>/<repo_name>/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
url_template: "http://github.com/smallstep/certificates/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
# Repository to push the app manifest to.
repository:
owner: smallstep
name: scoop-bucket
branch: main
# Git author used to commit to the repository.
# Defaults are shown.
commit_author:
name: goreleaserbot
email: goreleaser@smallstep.com
# The project name and current git tag are used in the format string.
commit_msg_template: "Scoop update for {{ .ProjectName }} version {{ .Tag }}"
# Your app's homepage.
# Default is empty.
homepage: "https://smallstep.com/docs/step-ca"
# Skip uploads for prerelease.
skip_upload: auto
# Your app's description.
# Default is empty.
description: "A private certificate authority (X.509 & SSH) & ACME server for secure automated certificate management, so you can use TLS everywhere & SSO for SSH."
# Your app's license
# Default is empty.
license: "Apache-2.0"
================================================
FILE: .version.sh
================================================
#!/usr/bin/env sh
read -r firstline < .VERSION
last_half="${firstline##*tag: }"
case "$last_half" in
v*)
version_string="${last_half%%[,)]*}"
;;
esac
echo "${version_string:-v0.0.0}"
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## TEMPLATE -- do not alter or remove
---
## [x.y.z] - aaaa-bb-cc
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
---
### [0.30.1] - 2026-03-18
- Fix release issue
### [0.30.0] - 2026-03-18
### Added
- Warn when ACME provisioner is configured without a database (smallstep/certificates#2526)
- Validate webhooks configured on the ca.json (smallstep/certificates#2570)
- Add HTTP transport decorator (smallstep/certificates#2533)
### Changed
- Upgrade HSM-enabled Docker images from Debian Bookworm (12) to Debian Trixie
(13) (smallstep/certificates#2493)
- Use JSON array format for Dockerfile's `CMD` instruction. This prevents shell
interpolation of environment variables like `CONFIGPATH` and `PWDPATH`,
ensuring consistent command execution. Commands can still be overridden via
Kubernetes or Docker configuration when needed (smallstep/certificates#2493)
### Fixed
- Fix CRL IssuingDistributionPoint marshaling to correctly unset `OnlyContainsUserCerts` and `OnlyContainsCACerts` flags (smallstep/certificates#2511)
- Fix CRL DER download content-disposition filename extension from `.der` to `.crl` (smallstep/certificates#2537)
- Fix SSH agent KMS when CA is configured with Prometheus instrumented signer (smallstep/certificates#2379)
- Return helpful error message when root certificate is not found (smallstep/certificates#1893)
- Fix missing version number when building step-ca from source archive (smallstep/certificates#2513)
- Fix potential panic if a certificate had an empty tcg-kp-AIKCertificate extended key usage (smallstep/certificates#2569)
- Fix CA startup when configured with SCEP and Google Cloud CAS (smallstep/certificates#2517)
- Close idle connections on client certificate renew (smallstep/certificates#2515)
## [0.29.0] - 2025-12-03
### Added
- Add support for YubiKeys 5.7.4+ (smallstep/certificates#2370)
- Support managed device ID OID for step attestation format (smallstep/certificates#2382)
- Add support for remote configuration of GCP Organization-Id (smallstep/certificates#2408)
- Add additional DOCKER_STEPCA_INIT_* envs for docker/entrypoint.sh (smallstep/certificates#2461)
- Add sd_notify support (smallstep/certificates#2463)
### Changed
- Use errgroup to shutdown services concurrently (smallstep/certificates#2343)
### Fixed
- Fix process hanging after SIGTERM (smallstep/certificates#2338)
- Disable execute permission on a few policy/engine source files (smallstep/certificates#2435)
- Fix backdate support for ACME provisioner (smallstep/certificates#2444)
### Security
- Authorization Bypass in ACME and SCEP Provisioners (smallstep/certificates#2491)
- Improper Authorization Check for SSH Certificate Revocation (smallstep/certificates#2491)
## [0.28.4] - 2025-07-13
### Added
- Add support for using key usage, extended key usage, and basic constraints
from certificate requests in certificate templates (smallstep/crypto#767)
- Allow to specify audience when generating JWK provisioner tokens (smallstep/certificates#2326)
- Add SSH certificate type to exposed metrics (smallstep/certificates#2290)
- Enable dynamic validation of project ownership within a GCP organization
when using the GCP Cloud Instance Identity provisioner (smallstep/certificates#2133)
### Changed
- Introduce poolhttp package for improved memory performance of Authority
httpClients (smallstep/certificates#2325)
## [0.28.3] - 2025-03-17
- dependabot updates
## [0.28.2] - 2025-02-20
### Added
- Added support for imported keys on YubiKey (smallstep/certificates#2113)
- Enable storing ACME attestation payload (smallstep/certificates#2114)
- Add ACME attestation format field to ACME challenge (smallstep/certificates#2124)
### Changed
- Added internal httptransport package to replace cloning of http.DefaultTransport (smallstep/certificates#2098, smallstep/certificates#2103, smallstep/certificates#2104)
- For example, replacing http.DefaultTransport clone in provisioner webhook business logic.
## [0.28.1] - 2024-11-19
### Added
- Support for using template data from SCEPCHALLENGE webhooks (smallstep/certificates#2065)
- New field to Webhook response that allows for propagation of human readable errors to the client (smallstep/certificates#2066, smallstep/certificates#2069)
- CICD for pushing DEB and RPM packages to packages.smallstep.com on releases (smallstep/certificates#2076)
- PKCS11 utilities in HSM container image (smallstep/certificates#2077)
### Changed
- Artifact names for RPM and DEB packages in conformance with standards (smallstep/certificates#2076)
## [0.28.0] - 2024-10-29
### Added
- Add options to GCP IID provisioner to enable or disable signing of SSH user and host certificates (smallstep/certificates#2045)
### Changed
- For IID provisioners with disableCustomSANs set to true, validate that the
requested DNS names are a subset of the allowed DNS names (based on the IID token),
rather than requiring an exact match to the entire list of allowed DNS names. (smallstep/certificates#2044)
## [0.27.5] - 2024-10-17
### Added
- Option to log real IP (x-forwarded-for) in logging middleware (smallstep/certificates#2002)
### Fixed
- Pulled in updates to smallstep/pkcs7 to fix failing Windows SCEP enrollment certificates (smallstep/certificates#1994)
## [0.27.4] - 2024-09-13
### Fixed
- Release worfklow
## [0.27.3] - 2024-09-13
### Added
- AWS auth method for Vault RA mode (smallstep/certificates#1976)
- API endpoints for retrieving Intermediate certificates (smallstep/certificates#1962)
- Enable use of OIDC provisioner with private identity providers and a certificate from step-ca (smallstep/certificates#1940)
- Support for verifying `cnf` and `x5rt#S256` claim when provided in token (smallstep/certificates#1660)
- Add Wire integration to ACME provisioner (smallstep/certificates#1666)
### Changed
- Clarified SSH certificate policy errors (smallstep/certificates#1951)
### Fixed
- Nebula ECDSA P-256 support (smallstep/certificates#1662)
## [0.27.2] - 2024-07-18
### Added
- `--console` option to default step-ssh config (smallstep/certificates#1931)
## [0.27.1] - 2024-07-12
### Changed
- Enable use of strict FQDN with a flag (smallstep/certificates#1926)
- This reverses a change in 0.27.0 that required the use of strict FQDNs (smallstep/certificate#1910)
## [0.27.0] - 2024-07-11
### Added
- Support for validity windows in templates (smallstep/certificates#1903)
- Create identity certificate with host URI when using any provisioner (smallstep/certificates#1922)
### Changed
- Do strict DNS lookup on ACME (smallstep/certificates#1910)
### Fixed
- Handle bad attestation object in deviceAttest01 validation (smallstep/certificates#1913)
## [0.26.2] - 2024-06-13
### Added
- Add provisionerID to ACME accounts (smallstep/certificates#1830)
- Enable verifying ACME provisioner using provisionerID if available (smallstep/certificates#1844)
- Add methods to Authority to get intermediate certificates (smallstep/certificates#1848)
- Add GetX509Signer method (smallstep/certificates#1850)
### Changed
- Make ISErrNotFound more flexible (smallstep/certificates#1819)
- Log errors using slog.Logger (smallstep/certificates#1849)
- Update hardcoded AWS certificates (smallstep/certificates#1881)
## [0.26.1] - 2024-04-22
### Added
- Allow configuration of a custom SCEP key manager (smallstep/certificates#1797)
### Fixed
- id-scep-failInfoText OID (smallstep/certificates#1794)
- CA startup with Vault RA configuration (smallstep/certificates#1803)
## [0.26.0] - 2024-03-28
### Added
- [TPM KMS](https://github.com/smallstep/crypto/tree/master/kms/tpmkms) support for CA keys (smallstep/certificates#1772)
- Propagation of HTTP request identifier using X-Request-Id header (smallstep/certificates#1743, smallstep/certificates#1542)
- Expires header in CRL response (smallstep/certificates#1708)
- Support for providing TLS configuration programmatically (smallstep/certificates#1685)
- Support for providing external CAS implementation (smallstep/certificates#1684)
- AWS `ca-west-1` identity document root certificate (smallstep/certificates#1715)
- [COSE RS1](https://www.rfc-editor.org/rfc/rfc8812.html#section-2) as a supported algorithm with ACME `device-attest-01` challenge (smallstep/certificates#1663)
### Changed
- In an RA setup, let the CA decide the RA certificate lifetime (smallstep/certificates#1764)
- Use Debian Bookworm in Docker containers (smallstep/certificates#1615)
- Error message for CSR validation (smallstep/certificates#1665)
- Updated dependencies
### Fixed
- Stop CA when any of the required servers fails to start (smallstep/certificates#1751). Before the fix, the CA would continue running and only log the server failure when stopped.
- Configuration loading errors when not using context were not returned. Fixed in [cli-utils/109](https://github.com/smallstep/cli-utils/pull/109).
- HTTP_PROXY and HTTPS_PROXY support for ACME validation client (smallstep/certificates#1658).
### Security
- Upgrade to using cosign v2 for signing artifacts
## [0.25.1] - 2023-11-28
### Added
- Provisioner name in SCEP webhook request body in (smallstep/certificates#1617)
- Support for ASN1 boolean encoding in (smallstep/certificates#1590)
### Changed
- Generation of first provisioner name on `step ca init` in (smallstep/certificates#1566)
- Processing of SCEP Get PKIOperation requests in (smallstep/certificates#1570)
- Support for signing identity certificate during SSH sign by skipping URI validation in (smallstep/certificates#1572)
- Dependency on `micromdm/scep` and `go.mozilla.org/pkcs7` to use Smallstep forks in (smallstep/certificates#1600)
- Make the Common Name validator for JWK provisioners accept values from SANs too in (smallstep/certificates#1609)
### Fixed
- Registration Authority token creation relied on values from CSR. Fixed to rely on template in (smallstep/certificates#1608)
- Use same glibc version for running the CA when built using CGo in (smallstep/certificates#1616)
## [0.25.0] - 2023-09-26
### Added
- Added support for configuring SCEP decrypters in the provisioner (smallstep/certificates#1414)
- Added support for TPM KMS (smallstep/crypto#253)
- Added support for disableSmallstepExtensions provisioner claim
(smallstep/certificates#1484)
- Added script to migrate a badger DB to MySQL or PostgreSQL
(smallstep/certificates#1477)
- Added AWS public certificates for me-central-1 and ap-southeast-3
(smallstep/certificates#1404)
- Added namespace field to VaultCAS JSON config (smallstep/certificates#1424)
- Added AWS public certificates for me-central-1 and ap-southeast-3
(smallstep/certificates#1404)
- Added unversioned filenames to Github release assets
(smallstep/certificates#1435)
- Send X5C leaf certificate to webhooks (smallstep/certificates#1485)
- Added support for disableSmallstepExtensions claim (smallstep/certificates#1484)
- Added all AWS Identity Document Certificates (smallstep/certificates#1404, smallstep/certificates#1510)
- Added Winget release automation (smallstep/certificates#1519)
- Added CSR to SCEPCHALLENGE webhook request body (smallstep/certificates#1523)
- Added SCEP issuance notification webhook (smallstep/certificates#1544)
- Added ability to disable color in the log text formatter
(smallstep/certificates(#1559)
### Changed
- Changed the Makefile to produce cgo-enabled builds running
`make build GO_ENVS="CGO_ENABLED=1"` (smallstep/certificates#1446)
- Return more detailed errors to ACME clients using device-attest-01
(smallstep/certificates#1495)
- Change SCEP password type to string (smallstep/certificates#1555)
### Removed
- Removed OIDC user regexp check (smallstep/certificates#1481)
- Removed automatic initialization of $STEPPATH (smallstep/certificates#1493)
- Removed db datasource from error msg to prevent leaking of secrets to logs
(smallstep/certificates#1528)
### Fixed
- Improved authentication for ACME requests using kid and provisioner name
(smallstep/certificates#1386).
- Fixed indentation of KMS configuration in helm charts
(smallstep/certificates#1405)
- Fixed simultaneous sign or decrypt operation on a YubiKey
(smallstep/certificates#1476, smallstep/crypto#288)
- Fixed adding certificate templates with ASN.1 functions
(smallstep/certificates#1500, smallstep/crypto#302)
- Fixed a problem when the ca.json is truncated if the encoding of the
configuration fails (e.g., new provisioner with bad template data)
(smallstep/cli#994, smallstep/certificates#1501)
- Fixed provisionerOptionsToLinkedCA missing template and templateData
(smallstep/certificates#1520)
- Fix calculation of webhook signature (smallstep/certificates#1546)
## [v0.24.2] - 2023-05-11
### Added
- Log SSH certificates (smallstep/certificates#1374)
- CRL endpoints on the HTTP server (smallstep/certificates#1372)
- Dynamic SCEP challenge validation using webhooks (smallstep/certificates#1366)
- For Docker deployments, added DOCKER_STEPCA_INIT_PASSWORD_FILE. Useful for pointing to a Docker Secret in the container (smallstep/certificates#1384)
### Changed
- Depend on [smallstep/go-attestation](https://github.com/smallstep/go-attestation) instead of [google/go-attestation](https://github.com/google/go-attestation)
- Render CRLs into http.ResponseWriter instead of memory (smallstep/certificates#1373)
- Redaction of SCEP static challenge when listing provisioners (smallstep/certificates#1204)
### Fixed
- VaultCAS certificate lifetime (smallstep/certificates#1376)
## [v0.24.1] - 2023-04-14
### Fixed
- Docker image name for HSM support (smallstep/certificates#1348)
## [v0.24.0] - 2023-04-12
### Added
- Add ACME `device-attest-01` support with TPM 2.0
(smallstep/certificates#1063).
- Add support for new Azure SDK, sovereign clouds, and HSM keys on Azure KMS
(smallstep/crypto#192, smallstep/crypto#197, smallstep/crypto#198,
smallstep/certificates#1323, smallstep/certificates#1309).
- Add support for ASN.1 functions on certificate templates
(smallstep/crypto#208, smallstep/certificates#1345)
- Add `DOCKER_STEPCA_INIT_ADDRESS` to configure the address to use in a docker
container (smallstep/certificates#1262).
- Make sure that the CSR used matches the attested key when using AME
`device-attest-01` challenge (smallstep/certificates#1265).
- Add support for compacting the Badger DB (smallstep/certificates#1298).
- Build and release cleanups (smallstep/certificates#1322,
smallstep/certificates#1329, smallstep/certificates#1340).
### Fixed
- Fix support for PKCS #7 RSA-OAEP decryption through
[smallstep/pkcs7#4](https://github.com/smallstep/pkcs7/pull/4), as used in
SCEP.
- Fix RA installation using `scripts/install-step-ra.sh`
(smallstep/certificates#1255).
- Clarify error messages on policy errors (smallstep/certificates#1287,
smallstep/certificates#1278).
- Clarify error message on OIDC email validation (smallstep/certificates#1290).
- Mark the IDP critical in the generated CRL data (smallstep/certificates#1293).
- Disable database if CA is initialized with the `--no-db` flag
(smallstep/certificates#1294).
## [v0.23.2] - 2023-02-02
### Added
- Added [`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin) to
docker images, and a new image, `smallstep/step-ca-hsm`, compiled with cgo
(smallstep/certificates#1243).
- Added [`scoop`](https://scoop.sh) packages back to the release
(smallstep/certificates#1250).
- Added optional flag `--pidfile` which allows passing a filename where step-ca
will write its process id (smallstep/certificates#1251).
- Added helpful message on CA startup when config can't be opened
(smallstep/certificates#1252).
- Improved validation and error messages on `device-attest-01` orders
(smallstep/certificates#1235).
### Removed
- The deprecated CLI utils `step-awskms-init`, `step-cloudkms-init`,
`step-pkcs11-init`, `step-yubikey-init` have been removed.
[`step`](https://github.com/smallstep/cli) and
[`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin) should be
used instead (smallstep/certificates#1240).
### Fixed
- Fixed remote management flags in docker images (smallstep/certificates#1228).
## [v0.23.1] - 2023-01-10
### Added
- Added configuration property `.crl.idpURL` to be able to set a custom Issuing
Distribution Point in the CRL (smallstep/certificates#1178).
- Added WithContext methods to the CA client (smallstep/certificates#1211).
- Docker: Added environment variables for enabling Remote Management and ACME
provisioner (smallstep/certificates#1201).
- Docker: The entrypoint script now generates and displays an initial JWK
provisioner password by default when the CA is being initialized
(smallstep/certificates#1223).
### Changed
- Ignore SSH principals validation when using an OIDC provisioner. The
provisioner will ignore the principals passed and set the defaults or the ones
including using WebHooks or templates (smallstep/certificates#1206).
## [v0.23.0] - 2022-11-11
### Added
- Added support for ACME device-attest-01 challenge on iOS, iPadOS, tvOS and
YubiKey.
- Ability to disable ACME challenges and attestation formats.
- Added flags to change ACME challenge ports for testing purposes.
- Added name constraints evaluation and enforcement when issuing or renewing
X.509 certificates.
- Added provisioner webhooks for augmenting template data and authorizing
certificate requests before signing.
- Added automatic migration of provisioners when enabling remote management.
- Added experimental support for CRLs.
- Add certificate renewal support on RA mode. The `step ca renew` command must
use the flag `--mtls=false` to use the token renewal flow.
- Added support for initializing remote management using `step ca init`.
- Added support for renewing X.509 certificates on RAs.
- Added support for using SCEP with keys in a KMS.
- Added client support to set the dialer's local address with the environment variable
`STEP_CLIENT_ADDR`.
### Changed
- Remove the email requirement for issuing SSH certificates with an OIDC
provisioner.
- Root files can contain more than one certificate.
### Fixed
- Fixed MySQL DSN parsing issues with an upgrade to
[smallstep/nosql@v0.5.0](https://github.com/smallstep/nosql/releases/tag/v0.5.0).
- Fixed renewal of certificates with missing subject attributes.
- Fixed ACME support with [ejabberd](https://github.com/processone/ejabberd).
### Deprecated
- The CLIs `step-awskms-init`, `step-cloudkms-init`, `step-pkcs11-init`,
`step-yubikey-init` are deprecated. Now you can use
[`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin) in
combination with `step certificates create` to initialize your PKI.
## [0.22.1] - 2022-08-31
### Fixed
- Fixed signature algorithm on EC (root) + RSA (intermediate) PKIs.
## [0.22.0] - 2022-08-26
### Added
- Added automatic configuration of Linked RAs.
- Send provisioner configuration on Linked RAs.
### Changed
- Certificates signed by an issuer using an RSA key will be signed using the
same algorithm used to sign the issuer certificate. The signature will no
longer default to PKCS #1. For example, if the issuer certificate was signed
using RSA-PSS with SHA-256, a new certificate will also be signed using
RSA-PSS with SHA-256.
- Support two latest versions of Go (1.18, 1.19).
- Validate revocation serial number (either base 10 or prefixed with an
appropriate base).
- Sanitize TLS options.
## [0.20.0] - 2022-05-26
### Added
- Added Kubernetes auth method for Vault RAs.
- Added support for reporting provisioners to linkedca.
- Added support for certificate policies on authority level.
- Added a Dockerfile with a step-ca build with HSM support.
- A few new WithXX methods for instantiating authorities
### Changed
- Context usage in HTTP APIs.
- Changed authentication for Vault RAs.
- Error message returned to client when authenticating with expired certificate.
- Strip padding from ACME CSRs.
### Deprecated
- HTTP API handler types.
### Fixed
- Fixed SSH revocation.
- CA client dial context for js/wasm target.
- Incomplete `extraNames` support in templates.
- SCEP GET request support.
- Large SCEP request handling.
## [0.19.0] - 2022-04-19
### Added
- Added support for certificate renewals after expiry using the claim `allowRenewalAfterExpiry`.
- Added support for `extraNames` in X.509 templates.
- Added `armv5` builds.
- Added RA support using a Vault instance as the CA.
- Added `WithX509SignerFunc` authority option.
- Added a new `/roots.pem` endpoint to download the CA roots in PEM format.
- Added support for Azure `Managed Identity` tokens.
- Added support for automatic configuration of linked RAs.
- Added support for the `--context` flag. It's now possible to start the
CA with `step-ca --context=abc` to use the configuration from context `abc`.
When a context has been configured and no configuration file is provided
on startup, the configuration for the current context is used.
- Added startup info logging and option to skip it (`--quiet`).
- Added support for renaming the CA (Common Name).
### Changed
- Made SCEP CA URL paths dynamic.
- Support two latest versions of Go (1.17, 1.18).
- Upgrade go.step.sm/crypto to v0.16.1.
- Upgrade go.step.sm/linkedca to v0.15.0.
### Deprecated
- Go 1.16 support.
### Removed
### Fixed
- Fixed admin credentials on RAs.
- Fixed ACME HTTP-01 challenges for IPv6 identifiers.
- Various improvements under the hood.
### Security
## [0.18.2] - 2022-03-01
### Added
- Added `subscriptionIDs` and `objectIDs` filters to the Azure provisioner.
- [NoSQL](https://github.com/smallstep/nosql/pull/21) package allows filtering
out database drivers using Go tags. For example, using the Go flag
`--tags=nobadger,nobbolt,nomysql` will only compile `step-ca` with the pgx
driver for PostgreSQL.
### Changed
- IPv6 addresses are normalized as IP addresses instead of hostnames.
- More descriptive JWK decryption error message.
- Make the X5C leaf certificate available to the templates using `{{ .AuthorizationCrt }}`.
### Fixed
- During provisioner add - validate provisioner configuration before storing to DB.
## [0.18.1] - 2022-02-03
### Added
- Support for ACME revocation.
- Replace hash function with an RSA SSH CA to "rsa-sha2-256".
- Support Nebula provisioners.
- Example Ansible configurations.
- Support PKCS#11 as a decrypter, as used by SCEP.
### Changed
- Automatically create database directory on `step ca init`.
- Slightly improve errors reported when a template has invalid content.
- Error reporting in logs and to clients.
### Fixed
- SCEP renewal using HTTPS on macOS.
## [0.18.0] - 2021-11-17
### Added
- Support for multiple certificate authority contexts.
- Support for generating extractable keys and certificates on a pkcs#11 module.
### Changed
- Support two latest versions of Go (1.16, 1.17)
### Deprecated
- go 1.15 support
## [0.17.6] - 2021-10-20
### Notes
- 0.17.5 failed in CI/CD
## [0.17.5] - 2021-10-20
### Added
- Support for Azure Key Vault as a KMS.
- Adapt `pki` package to support key managers.
- gocritic linter
### Fixed
- gocritic warnings
## [0.17.4] - 2021-09-28
### Fixed
- Support host-only or user-only SSH CA.
## [0.17.3] - 2021-09-24
### Added
- go 1.17 to github action test matrix
- Support for CloudKMS RSA-PSS signers without using templates.
- Add flags to support individual passwords for the intermediate and SSH keys.
- Global support for group admins in the OIDC provisioner.
### Changed
- Using go 1.17 for binaries
### Fixed
- Upgrade go-jose.v2 to fix a bug in the JWK fingerprint of Ed25519 keys.
### Security
- Use cosign to sign and upload signatures for multi-arch Docker container.
- Add debian checksum
## [0.17.2] - 2021-08-30
### Added
- Additional way to distinguish Azure IID and Azure OIDC tokens.
### Security
- Sign over all goreleaser github artifacts using cosign
## [0.17.1] - 2021-08-26
## [0.17.0] - 2021-08-25
### Added
- Add support for Linked CAs using protocol buffers and gRPC
- `step-ca init` adds support for
- configuring a StepCAS RA
- configuring a Linked CA
- congifuring a `step-ca` using Helm
### Changed
- Update badger driver to use v2 by default
- Update TLS cipher suites to include 1.3
### Security
- Fix key version when SHA512WithRSA is used. There was a typo creating RSA keys with SHA256 digests instead of SHA512.
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to `step certificates`
We welcome contributions to `step certificates` of any kind including
documentation, themes, organization, tutorials, blog posts, bug reports,
issues, feature requests, feature implementations, pull requests, helping
to manage issues, etc.
## Table of Contents
- [Contributing to `step certificates`](#contributing-to-step-certificates)
- [Table of Contents](#table-of-contents)
- [Building From Source](#building-from-source)
- [Build a standard `step-ca`](#build-a-standard-step-ca)
- [Build `step-ca` using CGO](#build-step-ca-using-cgo)
- [The CGO build enables PKCS #11 and YubiKey PIV support](#the-cgo-build-enables-pkcs-11-and-yubikey-piv-support)
- [1. Install PCSC support](#1-install-pcsc-support)
- [2. Build `step-ca`](#2-build-step-ca)
- [Asking Support Questions](#asking-support-questions)
- [Reporting Issues](#reporting-issues)
- [Code Contribution](#code-contribution)
- [Submitting Patches](#submitting-patches)
- [Code Contribution Guidelines](#code-contribution-guidelines)
- [Git Commit Message Guidelines](#git-commit-message-guidelines)
## Building From Source
Clone this repository to get a bleeding-edge build,
or download the source archive for [the latest stable release](https://github.com/smallstep/certificates/releases/latest).
### Build a standard `step-ca`
The only prerequisites are [`go`](https://golang.org/) and make.
To build from source:
make bootstrap && make
Find your binaries in `bin/`.
### Build `step-ca` using CGO
#### The CGO build enables PKCS #11 and YubiKey PIV support
To build the CGO version of `step-ca`, you will need [`go`](https://golang.org/), make, and a C compiler.
You'll also need PCSC support on your operating system, as required by the `go-piv` module.
On Linux, the [`libpcsclite-dev`](https://pcsclite.apdu.fr/) package provides PCSC support.
On macOS and Windows, PCSC support is built into the OS.
#### 1. Install PCSC support
On Debian-based distributions, run:
```shell
sudo apt-get install libpcsclite-dev
```
On Fedora:
```shell
sudo yum install pcsc-lite-devel
```
On CentOS:
```
sudo yum install 'dnf-command(config-manager)'
sudo yum config-manager --set-enabled PowerTools
sudo yum install pcsc-lite-devel
```
#### 2. Build `step-ca`
To build `step-ca`, clone this repository and run the following:
```shell
make bootstrap && make build GO_ENVS="CGO_ENABLED=1"
```
When the build is complete, you will find binaries in `bin/`.
## Asking Support Questions
Feel free to post a question on our [GitHub Discussions](https://github.com/smallstep/certificates/discussions) page, or find us on [Discord](https://bit.ly/step-discord).
## Reporting Issues
If you believe you have found a defect in `step certificates` or its
documentation, use the GitHub [issue
tracker](https://github.com/smallstep/certificates/issues) to report the
problem. When reporting the issue, please provide the version of `step
certificates` in use (`step-ca version`) and your operating system.
## Code Contribution
`step certificates` aims to become a fully featured online Certificate
Authority. We encourage all contributions that meet the following criteria:
* fit naturally into a Certificate Authority.
* strive not to break existing functionality.
* close or update an open [`step certificates`
issue](https://github.com/smallstep/certificates/issues)
**Bug fixes are, of course, always welcome.**
## Submitting Patches
`step certificates` welcomes all contributors and contributions. If you are
interested in helping with the project, please reach out to us or, better yet,
submit a PR :).
### Code Contribution Guidelines
Because we want to create the best possible product for our users and the best
contribution experience for our developers, we have a set of guidelines which
ensure that all contributions are acceptable. The guidelines are not intended
as a filter or barrier to participation. If you are unfamiliar with the
contribution process, the Smallstep team will guide you in order to get your
contribution in accordance with the guidelines.
To make the contribution process as seamless as possible, we ask for the following:
* Go ahead and fork the project and make your changes. We encourage pull
requests to allow for review and discussion of code changes.
* When you’re ready to create a pull request, be sure to:
* Sign the [CLA](https://cla-assistant.io/smallstep/certificates).
* Have test cases for the new code. If you have questions about how to do
this, please ask in your pull request.
* Run `go fmt`.
* Add documentation if you are adding new features or changing
functionality.
* Squash your commits into a single commit. `git rebase -i`. It’s okay to
force update your pull request with `git push -f`.
* Follow the **Git Commit Message Guidelines** below.
### Git Commit Message Guidelines
This [blog article](http://chris.beams.io/posts/git-commit/) is a good resource
for learning how to write good commit messages, the most important part being
that each commit message should have a title/subject in imperative mood
starting with a capital letter and no trailing period: *"Return error on wrong
use of the Paginator"*, **NOT** *"returning some error."*
Also, if your commit references one or more GitHub issues, always end your
commit message body with *See #1234* or *Fixes #1234*. Replace *1234* with the
GitHub issue ID. The last example will close the issue when the commit is
merged into *master*.
Please use a short and descriptive branch name, e.g. **NOT** "patch-1". It's
very common but creates a naming conflict each time when a submission is pulled
for a review.
An example:
```text
Add step certificate install
Add a command line utility for installing (and uninstalling) certificates to the
local system truststores. This should help developers with local development
flows.
Fixes #75
```
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 Smallstep Labs, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Makefile
================================================
PKG?=github.com/smallstep/certificates/cmd/step-ca
BINNAME?=step-ca
# Set V to 1 for verbose output from the Makefile
Q=$(if $V,,@)
PREFIX?=
SRC=$(shell find . -type f -name '*.go' -not -path "./vendor/*")
GOOS_OVERRIDE ?=
all: lint test build
ci: testcgo build
.PHONY: all ci
#########################################
# Bootstrapping
#########################################
bootstra%:
$Q curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin latest
$Q go install golang.org/x/vuln/cmd/govulncheck@latest
$Q go install gotest.tools/gotestsum@latest
$Q go install github.com/goreleaser/goreleaser/v2@latest
$Q go install github.com/sigstore/cosign/v2/cmd/cosign@latest
.PHONY: bootstra%
#################################################
# Determine the type of `push` and `version`
#################################################
# GITHUB Actions
ifdef GITHUB_REF
VERSION ?= $(shell echo $(GITHUB_REF) | sed 's/^refs\/tags\///')
NOT_RC := $(shell echo $(VERSION) | grep -v -e -rc)
ifeq ($(NOT_RC),)
PUSHTYPE := release-candidate
else
PUSHTYPE := release
endif
else
VERSION ?= $(shell [ -d .git ] && git describe --tags --always --dirty="-dev")
# If we are not in an active git dir then try reading the version from .VERSION.
# .VERSION contains a slug populated by `git archive`.
VERSION := $(or $(VERSION),$(shell ./.version.sh .VERSION))
PUSHTYPE := branch
endif
VERSION := $(shell echo $(VERSION) | sed 's/^v//')
ifdef V
$(info GITHUB_REF is $(GITHUB_REF))
$(info VERSION is $(VERSION))
$(info PUSHTYPE is $(PUSHTYPE))
endif
#########################################
# Build
#########################################
DATE := $(shell date -u '+%Y-%m-%d %H:%M UTC')
LDFLAGS := -ldflags='-w -X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"'
# Always explicitly enable or disable cgo,
# so that go doesn't silently fall back on
# non-cgo when gcc is not found.
ifeq (,$(findstring CGO_ENABLED,$(GO_ENVS)))
ifneq ($(origin GOFLAGS),undefined)
# This section is for backward compatibility with
#
# $ make build GOFLAGS=""
#
# which is how we recommended building step-ca with cgo support
# until June 2023.
GO_ENVS := $(GO_ENVS) CGO_ENABLED=1
else
GO_ENVS := $(GO_ENVS) CGO_ENABLED=0
endif
endif
download:
$Q go mod download
build: $(PREFIX)bin/$(BINNAME)
@echo "Build Complete!"
$(PREFIX)bin/$(BINNAME): download $(call rwildcard,*.go)
$Q mkdir -p $(@D)
$Q $(GOOS_OVERRIDE) GOFLAGS="$(GOFLAGS)" $(GO_ENVS) go build -v -o $(PREFIX)bin/$(BINNAME) $(LDFLAGS) $(PKG)
# Target to force a build of step-ca without running tests
simple: build
.PHONY: download build simple
#########################################
# Go generate
#########################################
generate:
$Q go generate ./...
.PHONY: generate
#########################################
# Test
#########################################
test: testdefault testtpmsimulator combinecoverage
testdefault:
$Q $(GO_ENVS) gotestsum -- -coverprofile=defaultcoverage.out -short -covermode=atomic ./...
testtpmsimulator:
$Q CGO_ENABLED=1 gotestsum -- -coverprofile=tpmsimulatorcoverage.out -short -covermode=atomic -tags tpmsimulator ./acme
testcgo:
$Q gotestsum -- -coverprofile=coverage.out -short -covermode=atomic ./...
combinecoverage:
cat defaultcoverage.out tpmsimulatorcoverage.out > coverage.out
.PHONY: test testdefault testtpmsimulator testcgo combinecoverage
integrate: integration
integration: bin/$(BINNAME)
$Q $(GO_ENVS) gotestsum -- -tags=integration ./integration/...
.PHONY: integrate integration
#########################################
# Linting
#########################################
fmt:
$Q goimports -l -w $(SRC)
lint: SHELL:=/bin/bash
lint:
$Q LOG_LEVEL=error golangci-lint run --config <(curl -s https://raw.githubusercontent.com/smallstep/workflows/master/.golangci.yml) --timeout=30m
$Q govulncheck ./...
.PHONY: fmt lint
#########################################
# Install
#########################################
INSTALL_PREFIX?=/usr/local/
install: $(PREFIX)bin/$(BINNAME)
$Q install -D $(PREFIX)bin/$(BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(BINNAME)
uninstall:
$Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BINNAME)
.PHONY: install uninstall
#########################################
# Clean
#########################################
clean:
ifneq ($(BINNAME),"")
$Q rm -f bin/$(BINNAME)
endif
.PHONY: clean
#########################################
# Dev
#########################################
run:
$Q go run cmd/step-ca/main.go $(shell step path)/config/ca.json
.PHONY: run
================================================
FILE: README.md
================================================
# step-ca
[](https://github.com/smallstep/certificates/releases/latest)
[](https://goreportcard.com/report/github.com/smallstep/certificates)
[](https://github.com/smallstep/certificates)
[](https://opensource.org/licenses/Apache-2.0)
[](https://cla-assistant.io/smallstep/certificates)
`step-ca` is an online certificate authority for secure, automated certificate management for DevOps.
It's the server counterpart to the [`step` CLI tool](https://github.com/smallstep/cli) for working with certificates and keys.
Both projects are maintained by [Smallstep Labs](https://smallstep.com).
You can use `step-ca` to:
- Issue HTTPS server and client certificates that [work in browsers](https://smallstep.com/blog/step-v0-8-6-valid-HTTPS-certificates-for-dev-pre-prod.html) ([RFC5280](https://tools.ietf.org/html/rfc5280) and [CA/Browser Forum](https://cabforum.org/baseline-requirements-documents/) compliance)
- Issue TLS certificates for DevOps: VMs, containers, APIs, database connections, Kubernetes pods...
- Issue SSH certificates:
- For people, in exchange for single sign-on identity tokens
- For hosts, in exchange for cloud instance identity documents
- Easily automate certificate management:
- It's an [ACME server](https://smallstep.com/docs/step-ca/acme-basics/) that supports all [popular ACME challenge types](https://smallstep.com/docs/step-ca/acme-basics/#acme-challenge-types)
- It comes with a [Go wrapper](./examples#user-content-basic-client-usage)
- ... and there's a [command-line client](https://github.com/smallstep/cli) you can use in scripts!
---
### Comparison with Smallstep's commercial product
`step-ca` is optimized for a two-tier PKI serving common DevOps use cases.
As you design your PKI, if you need any of the following, [consider our commerical CA](http://smallstep.com):
- Multiple certificate authorities
- Active revocation (CRL, OCSP)
- Turnkey high-volume, high availability CA
- An API for seamless IaC management of your PKI
- Integrated support for SCEP & NDES, for migrating from legacy Active Directory Certificate Services deployments
- Device identity — cross-platform device inventory and attestation using Secure Enclave & TPM 2.0
- Highly automated PKI — managed certificate renewal, monitoring, TPM-based attested enrollment
- Seamless client deployments of EAP-TLS Wi-Fi, VPN, SSH, and browser certificates
- Jamf, Intune, or other MDM for root distribution and client enrollment
- Web Admin UI — history, issuance, and metrics
- ACME External Account Binding (EAB)
- Deep integration with an identity provider
- Fine-grained, role-based access control
- FIPS-compliant software
- HSM-bound private keys
See our [full feature comparison](https://smallstep.com/step-ca-vs-smallstep-certificate-manager/) for more.
You can [start a free trial](https://smallstep.com/signup) or [set up a call with us](https://go.smallstep.com/request-demo) to learn more.
---
**Questions? Find us in [Discussions](https://github.com/smallstep/certificates/discussions) or [Join our Discord](https://u.step.sm/discord).**
[Website](https://smallstep.com/certificates) |
[Documentation](https://smallstep.com/docs/step-ca) |
[Installation](https://smallstep.com/docs/step-ca/installation) |
[Contributor's Guide](./CONTRIBUTING.md)
## Features
### 🦾 A fast, stable, flexible private CA
Setting up a *public key infrastructure* (PKI) is out of reach for many small teams. `step-ca` makes it easier.
- Choose key types (RSA, ECDSA, EdDSA) and lifetimes to suit your needs
- [Short-lived certificates](https://smallstep.com/blog/passive-revocation.html) with automated enrollment, renewal, and passive revocation
- Can operate as [an online intermediate CA for an existing root CA](https://smallstep.com/docs/tutorials/intermediate-ca-new-ca)
- [Badger, BoltDB, Postgres, and MySQL database backends](https://smallstep.com/docs/step-ca/configuration#databases)
### ⚙️ Many ways to automate
There are several ways to authorize a request with the CA and establish a chain of trust that suits your flow.
You can issue certificates in exchange for:
- [ACME challenge responses](#your-own-private-acme-server) from any ACMEv2 client
- [OAuth OIDC single sign-on tokens](https://smallstep.com/blog/easily-curl-services-secured-by-https-tls.html), eg:
- ID tokens from Okta, GSuite, Azure AD, Auth0.
- ID tokens from an OAuth OIDC service that you host, like [Keycloak](https://www.keycloak.org/) or [Dex](https://github.com/dexidp/dex)
- [Cloud instance identity documents](https://smallstep.com/blog/embarrassingly-easy-certificates-on-aws-azure-gcp/), for VMs on AWS, GCP, and Azure
- [Single-use, short-lived JWK tokens](https://smallstep.com/docs/step-ca/provisioners#jwk) issued by your CD tool — Puppet, Chef, Ansible, Terraform, etc.
- A trusted X.509 certificate (X5C provisioner)
- A host certificate from your Nebula network
- A SCEP challenge (SCEP provisioner)
- An SSH host certificates needing renewal (the SSHPOP provisioner)
- Learn more in our [provisioner documentation](https://smallstep.com/docs/step-ca/provisioners)
### 🏔 Your own private ACME server
ACME is the protocol used by Let's Encrypt to automate the issuance of HTTPS certificates. It's _super easy_ to issue certificates to any ACMEv2 ([RFC8555](https://tools.ietf.org/html/rfc8555)) client.
- [Use ACME in development & pre-production](https://smallstep.com/blog/private-acme-server/#local-development--pre-production)
- Supports the most popular [ACME challenge types](https://letsencrypt.org/docs/challenge-types/):
- For `http-01`, place a token at a well-known URL to prove that you control the web server
- For `dns-01`, add a `TXT` record to prove that you control the DNS record set
- For `tls-alpn-01`, respond to the challenge at the TLS layer ([as Caddy does](https://caddy.community/t/caddy-supports-the-acme-tls-alpn-challenge/4860)) to prove that you control the web server
- Works with any ACME client. We've written examples for:
- [certbot](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#certbot)
- [acme.sh](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#acmesh)
- [win-acme](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#win-acme)
- [Caddy](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#caddy-v2)
- [Traefik](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#traefik)
- [Apache](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#apache)
- [nginx](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#nginx)
- Get certificates programmatically using ACME, using these libraries:
- [`lego`](https://github.com/go-acme/lego) for Golang ([example usage](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#golang))
- certbot's [`acme` module](https://github.com/certbot/certbot/tree/master/acme) for Python ([example usage](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#python))
- [`acme-client`](https://github.com/publishlab/node-acme-client) for Node.js ([example usage](https://smallstep.com/docs/tutorials/acme-protocol-acme-clients#node))
- Our own [`step` CLI tool](https://github.com/smallstep/cli) is also an ACME client!
- See our [ACME tutorial](https://smallstep.com/docs/tutorials/acme-challenge) for more
### 👩🏽💻 An online SSH Certificate Authority
- Delegate SSH authentication to `step-ca` by using [SSH certificates](https://smallstep.com/blog/use-ssh-certificates/) instead of public keys and `authorized_keys` files
- For user certificates, [connect SSH to your single sign-on provider](https://smallstep.com/blog/diy-single-sign-on-for-ssh/), to improve security with short-lived certificates and MFA (or other security policies) via any OAuth OIDC provider.
- For host certificates, improve security, [eliminate TOFU warnings](https://smallstep.com/blog/use-ssh-certificates/), and set up automated host certificate renewal.
### 🤓 A general purpose PKI tool, via [`step` CLI](https://github.com/smallstep/cli) [integration](https://smallstep.com/docs/step-cli/reference/ca/)
- Generate key pairs where they're needed so private keys are never transmitted across the network
- [Authenticate and obtain a certificate](https://smallstep.com/docs/step-cli/reference/ca/certificate/) using any provisioner supported by `step-ca`
- Securely [distribute root certificates](https://smallstep.com/docs/step-cli/reference/ca/root/) and [bootstrap](https://smallstep.com/docs/step-cli/reference/ca/bootstrap/) PKI relying parties
- [Renew](https://smallstep.com/docs/step-cli/reference/ca/renew/) and [revoke](https://smallstep.com/docs/step-cli/reference/ca/revoke/) certificates issued by `step-ca`
- [Install root certificates](https://smallstep.com/docs/step-cli/reference/certificate/install/) on your machine and browsers, so your CA is trusted
- [Inspect](https://smallstep.com/docs/step-cli/reference/certificate/inspect/) and [lint](https://smallstep.com/docs/step-cli/reference/certificate/lint/) certificates
## Installation
See our installation docs [here](https://smallstep.com/docs/step-ca/installation).
## Documentation
* [Official documentation](https://smallstep.com/docs/step-ca) is on smallstep.com
* The `step` command reference is available via `step help`,
[on smallstep.com](https://smallstep.com/docs/step-cli/reference/),
or by running `step help --http=:8080` from the command line
and visiting http://localhost:8080.
## Feedback?
* Tell us what you like and don't like about managing your PKI - we're eager to help solve problems in this space. [Join our Discord](https://u.step.sm/discord) or [GitHub Discussions](https://github.com/smallstep/certificates/discussions)
* Tell us about a feature you'd like to see! [Request a Feature](https://github.com/smallstep/certificates/issues/new?assignees=&labels=enhancement%2C+needs+triage&template=enhancement.md&title=)
================================================
FILE: SECURITY.md
================================================
We appreciate any effort to discover and disclose security vulnerabilities responsibly.
If you would like to report a vulnerability in one of our projects, or have security concerns regarding Smallstep software, please email security@smallstep.com.
In order for us to best respond to your report, please include any of the following:
* Steps to reproduce or proof-of-concept
* Any relevant tools, including versions used
* Tool output
================================================
FILE: acme/account.go
================================================
package acme
import (
"crypto"
"encoding/base64"
"encoding/json"
"time"
"go.step.sm/crypto/jose"
"github.com/smallstep/certificates/authority/policy"
)
// Account is a subset of the internal account type containing only those
// attributes required for responses in the ACME protocol.
type Account struct {
ID string `json:"-"`
Key *jose.JSONWebKey `json:"-"`
Contact []string `json:"contact,omitempty"`
Status Status `json:"status"`
OrdersURL string `json:"orders"`
ExternalAccountBinding interface{} `json:"externalAccountBinding,omitempty"`
LocationPrefix string `json:"-"`
ProvisionerID string `json:"-"`
ProvisionerName string `json:"-"`
}
// GetLocation returns the URL location of the given account.
func (a *Account) GetLocation() string {
if a.LocationPrefix == "" {
return ""
}
return a.LocationPrefix + a.ID
}
// ToLog enables response logging.
func (a *Account) ToLog() (interface{}, error) {
b, err := json.Marshal(a)
if err != nil {
return nil, WrapErrorISE(err, "error marshaling account for logging")
}
return string(b), nil
}
// IsValid returns true if the Account is valid.
func (a *Account) IsValid() bool {
return a.Status == StatusValid
}
// KeyToID converts a JWK to a thumbprint.
func KeyToID(jwk *jose.JSONWebKey) (string, error) {
kid, err := jwk.Thumbprint(crypto.SHA256)
if err != nil {
return "", WrapErrorISE(err, "error generating jwk thumbprint")
}
return base64.RawURLEncoding.EncodeToString(kid), nil
}
// PolicyNames contains ACME account level policy names
type PolicyNames struct {
DNSNames []string `json:"dns"`
IPRanges []string `json:"ips"`
}
// X509Policy contains ACME account level X.509 policy
type X509Policy struct {
Allowed PolicyNames `json:"allow"`
Denied PolicyNames `json:"deny"`
AllowWildcardNames bool `json:"allowWildcardNames"`
}
// Policy is an ACME Account level policy
type Policy struct {
X509 X509Policy `json:"x509"`
}
func (p *Policy) GetAllowedNameOptions() *policy.X509NameOptions {
if p == nil {
return nil
}
return &policy.X509NameOptions{
DNSDomains: p.X509.Allowed.DNSNames,
IPRanges: p.X509.Allowed.IPRanges,
}
}
func (p *Policy) GetDeniedNameOptions() *policy.X509NameOptions {
if p == nil {
return nil
}
return &policy.X509NameOptions{
DNSDomains: p.X509.Denied.DNSNames,
IPRanges: p.X509.Denied.IPRanges,
}
}
// AreWildcardNamesAllowed returns if wildcard names
// like *.example.com are allowed to be signed.
// Defaults to false.
func (p *Policy) AreWildcardNamesAllowed() bool {
if p == nil {
return false
}
return p.X509.AllowWildcardNames
}
// ExternalAccountKey is an ACME External Account Binding key.
type ExternalAccountKey struct {
ID string `json:"id"`
ProvisionerID string `json:"provisionerID"`
Reference string `json:"reference"`
AccountID string `json:"-"`
HmacKey []byte `json:"-"`
CreatedAt time.Time `json:"createdAt"`
BoundAt time.Time `json:"boundAt,omitempty"`
Policy *Policy `json:"policy,omitempty"`
}
// AlreadyBound returns whether this EAK is already bound to
// an ACME Account or not.
func (eak *ExternalAccountKey) AlreadyBound() bool {
return !eak.BoundAt.IsZero()
}
// BindTo binds the EAK to an Account.
// It returns an error if it's already bound.
func (eak *ExternalAccountKey) BindTo(account *Account) error {
if eak.AlreadyBound() {
return NewError(ErrorUnauthorizedType, "external account binding key with id '%s' was already bound to account '%s' on %s", eak.ID, eak.AccountID, eak.BoundAt)
}
eak.AccountID = account.ID
eak.BoundAt = time.Now()
eak.HmacKey = []byte{} // clearing the key bytes; can only be used once
return nil
}
================================================
FILE: acme/account_test.go
================================================
package acme
import (
"crypto"
"encoding/base64"
"testing"
"time"
"github.com/pkg/errors"
"go.step.sm/crypto/jose"
"github.com/smallstep/assert"
)
func TestKeyToID(t *testing.T) {
type test struct {
jwk *jose.JSONWebKey
exp string
err *Error
}
tests := map[string]func(t *testing.T) test{
"fail/error-generating-thumbprint": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
jwk.Key = "foo"
return test{
jwk: jwk,
err: NewErrorISE("error generating jwk thumbprint: go-jose/go-jose: unknown key type 'string'"),
}
},
"ok": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
kid, err := jwk.Thumbprint(crypto.SHA256)
assert.FatalError(t, err)
return test{
jwk: jwk,
exp: base64.RawURLEncoding.EncodeToString(kid),
}
},
}
for name, run := range tests {
t.Run(name, func(t *testing.T) {
tc := run(t)
if id, err := KeyToID(tc.jwk); err != nil {
if assert.NotNil(t, tc.err) {
var k *Error
if errors.As(err, &k) {
assert.Equals(t, k.Type, tc.err.Type)
assert.Equals(t, k.Detail, tc.err.Detail)
assert.Equals(t, k.Status, tc.err.Status)
assert.Equals(t, k.Err.Error(), tc.err.Err.Error())
assert.Equals(t, k.Detail, tc.err.Detail)
} else {
assert.FatalError(t, errors.New("unexpected error type"))
}
}
} else {
if assert.Nil(t, tc.err) {
assert.Equals(t, id, tc.exp)
}
}
})
}
}
func TestAccount_GetLocation(t *testing.T) {
locationPrefix := "https://test.ca.smallstep.com/acme/foo/account/"
type test struct {
acc *Account
exp string
}
tests := map[string]test{
"empty": {acc: &Account{LocationPrefix: ""}, exp: ""},
"not-empty": {acc: &Account{ID: "bar", LocationPrefix: locationPrefix}, exp: locationPrefix + "bar"},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
assert.Equals(t, tc.acc.GetLocation(), tc.exp)
})
}
}
func TestAccount_IsValid(t *testing.T) {
type test struct {
acc *Account
exp bool
}
tests := map[string]test{
"valid": {acc: &Account{Status: StatusValid}, exp: true},
"invalid": {acc: &Account{Status: StatusInvalid}, exp: false},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
assert.Equals(t, tc.acc.IsValid(), tc.exp)
})
}
}
func TestExternalAccountKey_BindTo(t *testing.T) {
boundAt := time.Now()
tests := []struct {
name string
eak *ExternalAccountKey
acct *Account
err *Error
}{
{
name: "ok",
eak: &ExternalAccountKey{
ID: "eakID",
ProvisionerID: "provID",
Reference: "ref",
HmacKey: []byte{1, 3, 3, 7},
},
acct: &Account{
ID: "accountID",
},
err: nil,
},
{
name: "fail/already-bound",
eak: &ExternalAccountKey{
ID: "eakID",
ProvisionerID: "provID",
Reference: "ref",
HmacKey: []byte{1, 3, 3, 7},
AccountID: "someAccountID",
BoundAt: boundAt,
},
acct: &Account{
ID: "accountID",
},
err: NewError(ErrorUnauthorizedType, "external account binding key with id '%s' was already bound to account '%s' on %s", "eakID", "someAccountID", boundAt),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
eak := tt.eak
acct := tt.acct
err := eak.BindTo(acct)
wantErr := tt.err != nil
gotErr := err != nil
if wantErr != gotErr {
t.Errorf("ExternalAccountKey.BindTo() error = %v, wantErr %v", err, tt.err)
}
if wantErr {
assert.NotNil(t, err)
var ae *Error
if assert.True(t, errors.As(err, &ae)) {
assert.Equals(t, ae.Type, tt.err.Type)
assert.Equals(t, ae.Detail, tt.err.Detail)
assert.Equals(t, ae.Subproblems, tt.err.Subproblems)
}
} else {
assert.Equals(t, eak.AccountID, acct.ID)
assert.Equals(t, eak.HmacKey, []byte{})
assert.NotNil(t, eak.BoundAt)
}
})
}
}
================================================
FILE: acme/api/account.go
================================================
package api
import (
"context"
"encoding/json"
"errors"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/logging"
)
// NewAccountRequest represents the payload for a new account request.
type NewAccountRequest struct {
Contact []string `json:"contact"`
OnlyReturnExisting bool `json:"onlyReturnExisting"`
TermsOfServiceAgreed bool `json:"termsOfServiceAgreed"`
ExternalAccountBinding *ExternalAccountBinding `json:"externalAccountBinding,omitempty"`
}
func validateContacts(cs []string) error {
for _, c := range cs {
if c == "" {
return acme.NewError(acme.ErrorMalformedType, "contact cannot be empty string")
}
}
return nil
}
// Validate validates a new-account request body.
func (n *NewAccountRequest) Validate() error {
if n.OnlyReturnExisting && len(n.Contact) > 0 {
return acme.NewError(acme.ErrorMalformedType, "incompatible input; onlyReturnExisting must be alone")
}
return validateContacts(n.Contact)
}
// UpdateAccountRequest represents an update-account request.
type UpdateAccountRequest struct {
Contact []string `json:"contact"`
Status acme.Status `json:"status"`
}
// Validate validates a update-account request body.
func (u *UpdateAccountRequest) Validate() error {
switch {
case len(u.Status) > 0 && len(u.Contact) > 0:
return acme.NewError(acme.ErrorMalformedType, "incompatible input; contact and "+
"status updates are mutually exclusive")
case len(u.Contact) > 0:
if err := validateContacts(u.Contact); err != nil {
return err
}
return nil
case len(u.Status) > 0:
if u.Status != acme.StatusDeactivated {
return acme.NewError(acme.ErrorMalformedType, "cannot update account "+
"status to %s, only deactivated", u.Status)
}
return nil
default:
// According to the ACME spec (https://tools.ietf.org/html/rfc8555#section-7.3.2)
// accountUpdate should ignore any fields not recognized by the server.
return nil
}
}
// getAccountLocationPath returns the current account URL location.
// Returned location will be of the form: https://<ca-url>/acme/<provisioner>/account/<accID>
func getAccountLocationPath(ctx context.Context, linker acme.Linker, accID string) string {
return linker.GetLink(ctx, acme.AccountLinkType, accID)
}
// NewAccount is the handler resource for creating new ACME accounts.
func NewAccount(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
db := acme.MustDatabaseFromContext(ctx)
linker := acme.MustLinkerFromContext(ctx)
payload, err := payloadFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
var nar NewAccountRequest
if err := json.Unmarshal(payload.value, &nar); err != nil {
render.Error(w, r, acme.WrapError(acme.ErrorMalformedType, err,
"failed to unmarshal new-account request payload"))
return
}
if err := nar.Validate(); err != nil {
render.Error(w, r, err)
return
}
prov, err := acmeProvisionerFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
httpStatus := http.StatusCreated
acc, err := accountFromContext(ctx)
if err != nil {
var acmeErr *acme.Error
if !errors.As(err, &acmeErr) || acmeErr.Status != http.StatusBadRequest {
// Something went wrong ...
render.Error(w, r, err)
return
}
// Account does not exist //
if nar.OnlyReturnExisting {
render.Error(w, r, acme.NewError(acme.ErrorAccountDoesNotExistType,
"account does not exist"))
return
}
jwk, err := jwkFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
eak, err := validateExternalAccountBinding(ctx, &nar)
if err != nil {
render.Error(w, r, err)
return
}
acc = &acme.Account{
Key: jwk,
Contact: nar.Contact,
Status: acme.StatusValid,
LocationPrefix: getAccountLocationPath(ctx, linker, ""),
ProvisionerID: prov.ID,
ProvisionerName: prov.Name,
}
if err := db.CreateAccount(ctx, acc); err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error creating account"))
return
}
if eak != nil { // means that we have a (valid) External Account Binding key that should be bound, updated and sent in the response
if err := eak.BindTo(acc); err != nil {
render.Error(w, r, err)
return
}
if err := db.UpdateExternalAccountKey(ctx, prov.ID, eak); err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error updating external account binding key"))
return
}
acc.ExternalAccountBinding = nar.ExternalAccountBinding
}
} else {
// Account exists
httpStatus = http.StatusOK
}
linker.LinkAccount(ctx, acc)
w.Header().Set("Location", getAccountLocationPath(ctx, linker, acc.ID))
render.JSONStatus(w, r, acc, httpStatus)
}
// GetOrUpdateAccount is the api for updating an ACME account.
func GetOrUpdateAccount(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
db := acme.MustDatabaseFromContext(ctx)
linker := acme.MustLinkerFromContext(ctx)
acc, err := accountFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
payload, err := payloadFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
// If PostAsGet just respond with the account, otherwise process like a
// normal Post request.
if !payload.isPostAsGet {
var uar UpdateAccountRequest
if err := json.Unmarshal(payload.value, &uar); err != nil {
render.Error(w, r, acme.WrapError(acme.ErrorMalformedType, err,
"failed to unmarshal new-account request payload"))
return
}
if err := uar.Validate(); err != nil {
render.Error(w, r, err)
return
}
if len(uar.Status) > 0 || len(uar.Contact) > 0 {
if len(uar.Status) > 0 {
acc.Status = uar.Status
} else if len(uar.Contact) > 0 {
acc.Contact = uar.Contact
}
if err := db.UpdateAccount(ctx, acc); err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error updating account"))
return
}
}
}
linker.LinkAccount(ctx, acc)
w.Header().Set("Location", linker.GetLink(ctx, acme.AccountLinkType, acc.ID))
render.JSON(w, r, acc)
}
func logOrdersByAccount(w http.ResponseWriter, oids []string) {
if rl, ok := w.(logging.ResponseLogger); ok {
m := map[string]interface{}{
"orders": oids,
}
rl.WithFields(m)
}
}
// GetOrdersByAccountID ACME api for retrieving the list of order urls belonging to an account.
func GetOrdersByAccountID(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
db := acme.MustDatabaseFromContext(ctx)
linker := acme.MustLinkerFromContext(ctx)
acc, err := accountFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
accID := chi.URLParam(r, "accID")
if acc.ID != accID {
render.Error(w, r, acme.NewError(acme.ErrorUnauthorizedType, "account ID '%s' does not match url param '%s'", acc.ID, accID))
return
}
orders, err := db.GetOrdersByAccountID(ctx, acc.ID)
if err != nil {
render.Error(w, r, err)
return
}
linker.LinkOrdersByAccountID(ctx, orders)
render.JSON(w, r, orders)
logOrdersByAccount(w, orders)
}
================================================
FILE: acme/api/account_test.go
================================================
package api
import (
"bytes"
"context"
"crypto/x509"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/pkg/errors"
"go.step.sm/crypto/jose"
"github.com/smallstep/assert"
"github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/authority/provisioner"
)
var (
defaultDisableRenewal = false
defaultDisableSmallstepExtensions = false
globalProvisionerClaims = provisioner.Claims{
MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute},
MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
DefaultTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
DisableRenewal: &defaultDisableRenewal,
DisableSmallstepExtensions: &defaultDisableSmallstepExtensions,
}
)
type fakeProvisioner struct{}
func (*fakeProvisioner) AuthorizeOrderIdentifier(context.Context, provisioner.ACMEIdentifier) error {
return nil
}
func (*fakeProvisioner) AuthorizeSign(context.Context, string) ([]provisioner.SignOption, error) {
return nil, nil
}
func (*fakeProvisioner) IsChallengeEnabled(context.Context, provisioner.ACMEChallenge) bool {
return true
}
func (*fakeProvisioner) IsAttestationFormatEnabled(context.Context, provisioner.ACMEAttestationFormat) bool {
return true
}
func (*fakeProvisioner) GetAttestationRoots() (*x509.CertPool, bool) { return nil, false }
func (*fakeProvisioner) AuthorizeRevoke(context.Context, string) error { return nil }
func (*fakeProvisioner) GetID() string { return "" }
func (*fakeProvisioner) GetName() string { return "" }
func (*fakeProvisioner) DefaultTLSCertDuration() time.Duration { return 0 }
func (*fakeProvisioner) GetOptions() *provisioner.Options { return nil }
func newProv() acme.Provisioner {
// Initialize provisioners
p := &provisioner.ACME{
Type: "ACME",
Name: "test@acme-<test>provisioner.com",
}
if err := p.Init(provisioner.Config{Claims: globalProvisionerClaims}); err != nil {
fmt.Printf("%v", err)
}
return p
}
func newProvWithID() acme.Provisioner {
// Initialize provisioners
p := &provisioner.ACME{
ID: uuid.NewString(),
Type: "ACME",
Name: "test@acme-<test>provisioner.com",
}
if err := p.Init(provisioner.Config{Claims: globalProvisionerClaims}); err != nil {
fmt.Printf("%v", err)
}
return p
}
func newProvWithOptions(options *provisioner.Options) acme.Provisioner {
// Initialize provisioners
p := &provisioner.ACME{
Type: "ACME",
Name: "test@acme-<test>provisioner.com",
Options: options,
}
if err := p.Init(provisioner.Config{Claims: globalProvisionerClaims}); err != nil {
fmt.Printf("%v", err)
}
return p
}
func newACMEProv(t *testing.T) *provisioner.ACME {
p := newProv()
a, ok := p.(*provisioner.ACME)
if !ok {
t.Fatal("not a valid ACME provisioner")
}
return a
}
func newACMEProvWithOptions(t *testing.T, options *provisioner.Options) *provisioner.ACME {
p := newProvWithOptions(options)
a, ok := p.(*provisioner.ACME)
if !ok {
t.Fatal("not a valid ACME provisioner")
}
return a
}
func createEABJWS(jwk *jose.JSONWebKey, hmacKey []byte, keyID, u string) (*jose.JSONWebSignature, error) {
signer, err := jose.NewSigner(
jose.SigningKey{
Algorithm: jose.SignatureAlgorithm("HS256"),
Key: hmacKey,
},
&jose.SignerOptions{
ExtraHeaders: map[jose.HeaderKey]interface{}{
"kid": keyID,
"url": u,
},
EmbedJWK: false,
},
)
if err != nil {
return nil, err
}
jwkJSONBytes, err := jwk.Public().MarshalJSON()
if err != nil {
return nil, err
}
jws, err := signer.Sign(jwkJSONBytes)
if err != nil {
return nil, err
}
raw, err := jws.CompactSerialize()
if err != nil {
return nil, err
}
parsedJWS, err := jose.ParseJWS(raw)
if err != nil {
return nil, err
}
return parsedJWS, nil
}
func createRawEABJWS(jwk *jose.JSONWebKey, hmacKey []byte, keyID, u string) ([]byte, error) {
jws, err := createEABJWS(jwk, hmacKey, keyID, u)
if err != nil {
return nil, err
}
rawJWS := jws.FullSerialize()
return []byte(rawJWS), nil
}
func TestNewAccountRequest_Validate(t *testing.T) {
type test struct {
nar *NewAccountRequest
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/incompatible-input": func(t *testing.T) test {
return test{
nar: &NewAccountRequest{
OnlyReturnExisting: true,
Contact: []string{"foo", "bar"},
},
err: acme.NewError(acme.ErrorMalformedType, "incompatible input; onlyReturnExisting must be alone"),
}
},
"fail/bad-contact": func(t *testing.T) test {
return test{
nar: &NewAccountRequest{
Contact: []string{"foo", ""},
},
err: acme.NewError(acme.ErrorMalformedType, "contact cannot be empty string"),
}
},
"ok": func(t *testing.T) test {
return test{
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
},
}
},
"ok/onlyReturnExisting": func(t *testing.T) test {
return test{
nar: &NewAccountRequest{
OnlyReturnExisting: true,
},
}
},
}
for name, run := range tests {
tc := run(t)
t.Run(name, func(t *testing.T) {
if err := tc.nar.Validate(); err != nil {
if assert.NotNil(t, err) {
var ae *acme.Error
if assert.True(t, errors.As(err, &ae)) {
assert.HasPrefix(t, ae.Error(), tc.err.Error())
assert.Equals(t, ae.StatusCode(), tc.err.StatusCode())
assert.Equals(t, ae.Type, tc.err.Type)
}
}
} else {
assert.Nil(t, tc.err)
}
})
}
}
func TestUpdateAccountRequest_Validate(t *testing.T) {
type test struct {
uar *UpdateAccountRequest
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/incompatible-input": func(t *testing.T) test {
return test{
uar: &UpdateAccountRequest{
Contact: []string{"foo", "bar"},
Status: "foo",
},
err: acme.NewError(acme.ErrorMalformedType, "incompatible input; "+
"contact and status updates are mutually exclusive"),
}
},
"fail/bad-contact": func(t *testing.T) test {
return test{
uar: &UpdateAccountRequest{
Contact: []string{"foo", ""},
},
err: acme.NewError(acme.ErrorMalformedType, "contact cannot be empty string"),
}
},
"fail/bad-status": func(t *testing.T) test {
return test{
uar: &UpdateAccountRequest{
Status: "foo",
},
err: acme.NewError(acme.ErrorMalformedType, "cannot update account "+
"status to foo, only deactivated"),
}
},
"ok/contact": func(t *testing.T) test {
return test{
uar: &UpdateAccountRequest{
Contact: []string{"foo", "bar"},
},
}
},
"ok/status": func(t *testing.T) test {
return test{
uar: &UpdateAccountRequest{
Status: "deactivated",
},
}
},
"ok/accept-empty": func(t *testing.T) test {
return test{
uar: &UpdateAccountRequest{},
}
},
}
for name, run := range tests {
tc := run(t)
t.Run(name, func(t *testing.T) {
if err := tc.uar.Validate(); err != nil {
if assert.NotNil(t, err) {
var ae *acme.Error
if assert.True(t, errors.As(err, &ae)) {
assert.HasPrefix(t, ae.Error(), tc.err.Error())
assert.Equals(t, ae.StatusCode(), tc.err.StatusCode())
assert.Equals(t, ae.Type, tc.err.Type)
}
}
} else {
assert.Nil(t, tc.err)
}
})
}
}
func TestHandler_GetOrdersByAccountID(t *testing.T) {
accID := "account-id"
// Request with chi context
chiCtx := chi.NewRouteContext()
chiCtx.URLParams.Add("accID", accID)
prov := newProv()
provName := url.PathEscape(prov.GetName())
baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"}
u := fmt.Sprintf("http://ca.smallstep.com/acme/%s/account/%s/orders", provName, accID)
oids := []string{"foo", "bar"}
oidURLs := []string{
fmt.Sprintf("%s/acme/%s/order/foo", baseURL.String(), provName),
fmt.Sprintf("%s/acme/%s/order/bar", baseURL.String(), provName),
}
type test struct {
db acme.DB
ctx context.Context
statusCode int
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/no-account": func(t *testing.T) test {
return test{
db: &acme.MockDB{},
ctx: context.Background(),
statusCode: 400,
err: acme.NewError(acme.ErrorAccountDoesNotExistType, "account does not exist"),
}
},
"fail/nil-account": func(t *testing.T) test {
return test{
db: &acme.MockDB{},
ctx: context.WithValue(context.Background(), accContextKey, http.NoBody),
statusCode: 400,
err: acme.NewError(acme.ErrorAccountDoesNotExistType, "account does not exist"),
}
},
"fail/account-id-mismatch": func(t *testing.T) test {
acc := &acme.Account{ID: "foo"}
ctx := context.WithValue(context.Background(), accContextKey, acc)
ctx = context.WithValue(ctx, chi.RouteCtxKey, chiCtx)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 401,
err: acme.NewError(acme.ErrorUnauthorizedType, "account ID does not match url param"),
}
},
"fail/db.GetOrdersByAccountID-error": func(t *testing.T) test {
acc := &acme.Account{ID: accID}
ctx := context.WithValue(context.Background(), accContextKey, acc)
ctx = context.WithValue(ctx, chi.RouteCtxKey, chiCtx)
return test{
db: &acme.MockDB{
MockError: acme.NewErrorISE("force"),
},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("force"),
}
},
"ok": func(t *testing.T) test {
acc := &acme.Account{ID: accID}
ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiCtx)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, accContextKey, acc)
return test{
db: &acme.MockDB{
MockGetOrdersByAccountID: func(ctx context.Context, id string) ([]string, error) {
assert.Equals(t, id, acc.ID)
return oids, nil
},
},
ctx: ctx,
statusCode: 200,
}
},
}
for name, run := range tests {
tc := run(t)
t.Run(name, func(t *testing.T) {
ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil)
req := httptest.NewRequest("GET", u, http.NoBody)
req = req.WithContext(ctx)
w := httptest.NewRecorder()
GetOrdersByAccountID(w, req)
res := w.Result()
assert.Equals(t, res.StatusCode, tc.statusCode)
body, err := io.ReadAll(res.Body)
res.Body.Close()
assert.FatalError(t, err)
if res.StatusCode >= 400 && assert.NotNil(t, tc.err) {
var ae acme.Error
assert.FatalError(t, json.Unmarshal(bytes.TrimSpace(body), &ae))
assert.Equals(t, ae.Type, tc.err.Type)
assert.Equals(t, ae.Detail, tc.err.Detail)
assert.Equals(t, ae.Subproblems, tc.err.Subproblems)
assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"})
} else {
expB, err := json.Marshal(oidURLs)
assert.FatalError(t, err)
assert.Equals(t, bytes.TrimSpace(body), expB)
assert.Equals(t, res.Header["Content-Type"], []string{"application/json"})
}
})
}
}
func TestHandler_NewAccount(t *testing.T) {
prov := newProv()
escProvName := url.PathEscape(prov.GetName())
baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"}
provID := prov.GetID()
type test struct {
db acme.DB
acc *acme.Account
ctx context.Context
statusCode int
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/no-payload": func(t *testing.T) test {
return test{
db: &acme.MockDB{},
ctx: context.Background(),
statusCode: 500,
err: acme.NewErrorISE("payload expected in request context"),
}
},
"fail/nil-payload": func(t *testing.T) test {
ctx := context.WithValue(context.Background(), payloadContextKey, nil)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("payload expected in request context"),
}
},
"fail/unmarshal-payload-error": func(t *testing.T) test {
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorMalformedType, "failed to "+
"unmarshal new-account request payload: unexpected end of JSON input"),
}
},
"fail/malformed-payload-error": func(t *testing.T) test {
nar := &NewAccountRequest{
Contact: []string{"foo", ""},
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorMalformedType, "contact cannot be empty string"),
}
},
"fail/no-existing-account": func(t *testing.T) test {
nar := &NewAccountRequest{
OnlyReturnExisting: true,
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = acme.NewProvisionerContext(ctx, prov)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorAccountDoesNotExistType, "account does not exist"),
}
},
"fail/no-jwk": func(t *testing.T) test {
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("jwk expected in request context"),
}
},
"fail/nil-jwk": func(t *testing.T) test {
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, jwkContextKey, nil)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("jwk expected in request context"),
}
},
"fail/new-account-no-eab-provided": func(t *testing.T) test {
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: nil,
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorExternalAccountRequiredType, "no external account binding provided"),
}
},
"fail/db.CreateAccount-error": func(t *testing.T) test {
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwkContextKey, jwk)
return test{
db: &acme.MockDB{
MockCreateAccount: func(ctx context.Context, acc *acme.Account) error {
assert.Equals(t, acc.Contact, nar.Contact)
assert.Equals(t, acc.Key, jwk)
return acme.NewErrorISE("force")
},
},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("force"),
}
},
"fail/acmeProvisionerFromContext": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, &fakeProvisioner{})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 500,
err: acme.NewError(acme.ErrorServerInternalType, "provisioner in context is not an ACME provisioner"),
}
},
"fail/db.UpdateExternalAccountKey-error": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: payloadBytes})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
eak := &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: time.Now(),
}
return test{
db: &acme.MockDB{
MockCreateAccount: func(ctx context.Context, acc *acme.Account) error {
acc.ID = "accountID"
assert.Equals(t, acc.Contact, nar.Contact)
assert.Equals(t, acc.Key, jwk)
return nil
},
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return eak, nil
},
MockUpdateExternalAccountKey: func(ctx context.Context, provisionerName string, eak *acme.ExternalAccountKey) error {
return errors.New("force")
},
},
acc: &acme.Account{
ID: "accountID",
Key: jwk,
Status: acme.StatusValid,
Contact: []string{"foo", "bar"},
OrdersURL: fmt.Sprintf("%s/acme/%s/account/accountID/orders", baseURL.String(), escProvName),
ExternalAccountBinding: eab,
},
ctx: ctx,
statusCode: 500,
err: acme.NewError(acme.ErrorServerInternalType, "error updating external account binding key"),
}
},
"ok/new-account": func(t *testing.T) test {
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
return test{
db: &acme.MockDB{
MockCreateAccount: func(ctx context.Context, acc *acme.Account) error {
acc.ID = "accountID"
assert.Equals(t, acc.Contact, nar.Contact)
assert.Equals(t, acc.Key, jwk)
return nil
},
},
acc: &acme.Account{
ID: "accountID",
Key: jwk,
Status: acme.StatusValid,
Contact: []string{"foo", "bar"},
OrdersURL: fmt.Sprintf("%s/acme/%s/account/accountID/orders", baseURL.String(), escProvName),
},
ctx: ctx,
statusCode: 201,
}
},
"ok/return-existing": func(t *testing.T) test {
nar := &NewAccountRequest{
OnlyReturnExisting: true,
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
acc := &acme.Account{
ID: "accountID",
Key: jwk,
Status: acme.StatusValid,
Contact: []string{"foo", "bar"},
}
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, accContextKey, acc)
return test{
db: &acme.MockDB{},
ctx: ctx,
acc: acc,
statusCode: 200,
}
},
"ok/new-account-no-eab-required": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = false
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
return test{
db: &acme.MockDB{
MockCreateAccount: func(ctx context.Context, acc *acme.Account) error {
acc.ID = "accountID"
assert.Equals(t, acc.Contact, nar.Contact)
assert.Equals(t, acc.Key, jwk)
return nil
},
},
acc: &acme.Account{
ID: "accountID",
Key: jwk,
Status: acme.StatusValid,
Contact: []string{"foo", "bar"},
OrdersURL: fmt.Sprintf("%s/acme/%s/account/accountID/orders", baseURL.String(), escProvName),
},
ctx: ctx,
statusCode: 201,
}
},
"ok/new-account-with-eab": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: payloadBytes})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockCreateAccount: func(ctx context.Context, acc *acme.Account) error {
acc.ID = "accountID"
assert.Equals(t, acc.Contact, nar.Contact)
assert.Equals(t, acc.Key, jwk)
return nil
},
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: time.Now(),
}, nil
},
MockUpdateExternalAccountKey: func(ctx context.Context, provisionerName string, eak *acme.ExternalAccountKey) error {
return nil
},
},
acc: &acme.Account{
ID: "accountID",
Key: jwk,
Status: acme.StatusValid,
Contact: []string{"foo", "bar"},
OrdersURL: fmt.Sprintf("%s/acme/%s/account/accountID/orders", baseURL.String(), escProvName),
ExternalAccountBinding: eab,
},
ctx: ctx,
statusCode: 201,
}
},
}
for name, run := range tests {
tc := run(t)
t.Run(name, func(t *testing.T) {
ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil)
req := httptest.NewRequest("GET", "/foo/bar", http.NoBody)
req = req.WithContext(ctx)
w := httptest.NewRecorder()
NewAccount(w, req)
res := w.Result()
assert.Equals(t, res.StatusCode, tc.statusCode)
body, err := io.ReadAll(res.Body)
res.Body.Close()
assert.FatalError(t, err)
if res.StatusCode >= 400 && assert.NotNil(t, tc.err) {
var ae acme.Error
assert.FatalError(t, json.Unmarshal(bytes.TrimSpace(body), &ae))
assert.Equals(t, ae.Type, tc.err.Type)
assert.Equals(t, ae.Detail, tc.err.Detail)
assert.Equals(t, ae.Subproblems, tc.err.Subproblems)
assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"})
} else {
expB, err := json.Marshal(tc.acc)
assert.FatalError(t, err)
assert.Equals(t, bytes.TrimSpace(body), expB)
assert.Equals(t, res.Header["Location"],
[]string{fmt.Sprintf("%s/acme/%s/account/%s", baseURL.String(),
escProvName, "accountID")})
assert.Equals(t, res.Header["Content-Type"], []string{"application/json"})
}
})
}
}
func TestHandler_GetOrUpdateAccount(t *testing.T) {
accID := "accountID"
acc := acme.Account{
ID: accID,
Status: "valid",
OrdersURL: fmt.Sprintf("https://ca.smallstep.com/acme/account/%s/orders", accID),
}
prov := newProv()
escProvName := url.PathEscape(prov.GetName())
baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"}
type test struct {
db acme.DB
ctx context.Context
statusCode int
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/no-account": func(t *testing.T) test {
return test{
db: &acme.MockDB{},
ctx: context.Background(),
statusCode: 400,
err: acme.NewError(acme.ErrorAccountDoesNotExistType, "account does not exist"),
}
},
"fail/nil-account": func(t *testing.T) test {
ctx := context.WithValue(context.Background(), accContextKey, nil)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorAccountDoesNotExistType, "account does not exist"),
}
},
"fail/no-payload": func(t *testing.T) test {
ctx := context.WithValue(context.Background(), accContextKey, &acc)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("payload expected in request context"),
}
},
"fail/nil-payload": func(t *testing.T) test {
ctx := context.WithValue(context.Background(), accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, nil)
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("payload expected in request context"),
}
},
"fail/unmarshal-payload-error": func(t *testing.T) test {
ctx := context.WithValue(context.Background(), accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorMalformedType, "failed to unmarshal new-account request payload: unexpected end of JSON input"),
}
},
"fail/malformed-payload-error": func(t *testing.T) test {
uar := &UpdateAccountRequest{
Contact: []string{"foo", ""},
}
b, err := json.Marshal(uar)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 400,
err: acme.NewError(acme.ErrorMalformedType, "contact cannot be empty string"),
}
},
"fail/db.UpdateAccount-error": func(t *testing.T) test {
uar := &UpdateAccountRequest{
Status: "deactivated",
}
b, err := json.Marshal(uar)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{
MockUpdateAccount: func(ctx context.Context, upd *acme.Account) error {
assert.Equals(t, upd.Status, acme.StatusDeactivated)
assert.Equals(t, upd.ID, acc.ID)
return acme.NewErrorISE("force")
},
},
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE("force"),
}
},
"ok/deactivate": func(t *testing.T) test {
uar := &UpdateAccountRequest{
Status: "deactivated",
}
b, err := json.Marshal(uar)
assert.FatalError(t, err)
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{
MockUpdateAccount: func(ctx context.Context, upd *acme.Account) error {
assert.Equals(t, upd.Status, acme.StatusDeactivated)
assert.Equals(t, upd.ID, acc.ID)
return nil
},
},
ctx: ctx,
statusCode: 200,
}
},
"ok/update-empty": func(t *testing.T) test {
uar := &UpdateAccountRequest{}
b, err := json.Marshal(uar)
assert.FatalError(t, err)
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 200,
}
},
"ok/update-contacts": func(t *testing.T) test {
uar := &UpdateAccountRequest{
Contact: []string{"foo", "bar"},
}
b, err := json.Marshal(uar)
assert.FatalError(t, err)
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{value: b})
return test{
db: &acme.MockDB{
MockUpdateAccount: func(ctx context.Context, upd *acme.Account) error {
assert.Equals(t, upd.Contact, uar.Contact)
assert.Equals(t, upd.ID, acc.ID)
return nil
},
},
ctx: ctx,
statusCode: 200,
}
},
"ok/post-as-get": func(t *testing.T) test {
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, accContextKey, &acc)
ctx = context.WithValue(ctx, payloadContextKey, &payloadInfo{isPostAsGet: true})
return test{
db: &acme.MockDB{},
ctx: ctx,
statusCode: 200,
}
},
}
for name, run := range tests {
tc := run(t)
t.Run(name, func(t *testing.T) {
ctx := acme.NewContext(tc.ctx, tc.db, nil, acme.NewLinker("test.ca.smallstep.com", "acme"), nil)
req := httptest.NewRequest("GET", "/foo/bar", http.NoBody)
req = req.WithContext(ctx)
w := httptest.NewRecorder()
GetOrUpdateAccount(w, req)
res := w.Result()
assert.Equals(t, res.StatusCode, tc.statusCode)
body, err := io.ReadAll(res.Body)
res.Body.Close()
assert.FatalError(t, err)
if res.StatusCode >= 400 && assert.NotNil(t, tc.err) {
var ae acme.Error
assert.FatalError(t, json.Unmarshal(bytes.TrimSpace(body), &ae))
assert.Equals(t, ae.Type, tc.err.Type)
assert.Equals(t, ae.Detail, tc.err.Detail)
assert.Equals(t, ae.Subproblems, tc.err.Subproblems)
assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"})
} else {
expB, err := json.Marshal(acc)
assert.FatalError(t, err)
assert.Equals(t, bytes.TrimSpace(body), expB)
assert.Equals(t, res.Header["Location"],
[]string{fmt.Sprintf("%s/acme/%s/account/%s", baseURL.String(),
escProvName, accID)})
assert.Equals(t, res.Header["Content-Type"], []string{"application/json"})
}
})
}
}
================================================
FILE: acme/api/eab.go
================================================
package api
import (
"context"
"encoding/json"
"errors"
"go.step.sm/crypto/jose"
"github.com/smallstep/certificates/acme"
)
// ExternalAccountBinding represents the ACME externalAccountBinding JWS
type ExternalAccountBinding struct {
Protected string `json:"protected"`
Payload string `json:"payload"`
Sig string `json:"signature"`
}
// validateExternalAccountBinding validates the externalAccountBinding property in a call to new-account.
func validateExternalAccountBinding(ctx context.Context, nar *NewAccountRequest) (*acme.ExternalAccountKey, error) {
acmeProv, err := acmeProvisionerFromContext(ctx)
if err != nil {
return nil, acme.WrapErrorISE(err, "could not load ACME provisioner from context")
}
if !acmeProv.RequireEAB {
//nolint:nilnil // legacy
return nil, nil
}
if nar.ExternalAccountBinding == nil {
return nil, acme.NewError(acme.ErrorExternalAccountRequiredType, "no external account binding provided")
}
eabJSONBytes, err := json.Marshal(nar.ExternalAccountBinding)
if err != nil {
return nil, acme.WrapErrorISE(err, "error marshaling externalAccountBinding into bytes")
}
eabJWS, err := jose.ParseJWS(string(eabJSONBytes))
if err != nil {
return nil, acme.WrapErrorISE(err, "error parsing externalAccountBinding jws")
}
// TODO(hs): implement strategy pattern to allow for different ways of verification (i.e. webhook call) based on configuration?
keyID, acmeErr := validateEABJWS(ctx, eabJWS)
if acmeErr != nil {
return nil, acmeErr
}
db := acme.MustDatabaseFromContext(ctx)
externalAccountKey, err := db.GetExternalAccountKey(ctx, acmeProv.ID, keyID)
if err != nil {
var ae *acme.Error
if errors.As(err, &ae) {
return nil, acme.WrapError(acme.ErrorUnauthorizedType, err, "the field 'kid' references an unknown key")
}
return nil, acme.WrapErrorISE(err, "error retrieving external account key")
}
if externalAccountKey == nil {
return nil, acme.NewError(acme.ErrorUnauthorizedType, "the field 'kid' references an unknown key")
}
if len(externalAccountKey.HmacKey) == 0 {
return nil, acme.NewError(acme.ErrorServerInternalType, "external account binding key with id '%s' does not have secret bytes", keyID)
}
if externalAccountKey.AlreadyBound() {
return nil, acme.NewError(acme.ErrorUnauthorizedType, "external account binding key with id '%s' was already bound to account '%s' on %s", keyID, externalAccountKey.AccountID, externalAccountKey.BoundAt)
}
payload, err := eabJWS.Verify(externalAccountKey.HmacKey)
if err != nil {
return nil, acme.WrapErrorISE(err, "error verifying externalAccountBinding signature")
}
jwk, err := jwkFromContext(ctx)
if err != nil {
return nil, err
}
var payloadJWK *jose.JSONWebKey
if err = json.Unmarshal(payload, &payloadJWK); err != nil {
return nil, acme.WrapError(acme.ErrorMalformedType, err, "error unmarshaling payload into jwk")
}
if !keysAreEqual(jwk, payloadJWK) {
return nil, acme.NewError(acme.ErrorUnauthorizedType, "keys in jws and eab payload do not match")
}
return externalAccountKey, nil
}
// keysAreEqual performs an equality check on two JWKs by comparing
// the (base64 encoding) of the Key IDs.
func keysAreEqual(x, y *jose.JSONWebKey) bool {
if x == nil || y == nil {
return false
}
digestX, errX := acme.KeyToID(x)
digestY, errY := acme.KeyToID(y)
if errX != nil || errY != nil {
return false
}
return digestX == digestY
}
// validateEABJWS verifies the contents of the External Account Binding JWS.
// The protected header of the JWS MUST meet the following criteria:
//
// - The "alg" field MUST indicate a MAC-based algorithm
// - The "kid" field MUST contain the key identifier provided by the CA
// - The "nonce" field MUST NOT be present
// - The "url" field MUST be set to the same value as the outer JWS
func validateEABJWS(ctx context.Context, jws *jose.JSONWebSignature) (string, *acme.Error) {
if jws == nil {
return "", acme.NewErrorISE("no JWS provided")
}
if len(jws.Signatures) != 1 {
return "", acme.NewError(acme.ErrorMalformedType, "JWS must have one signature")
}
header := jws.Signatures[0].Protected
algorithm := header.Algorithm
keyID := header.KeyID
nonce := header.Nonce
if algorithm != jose.HS256 && algorithm != jose.HS384 && algorithm != jose.HS512 {
return "", acme.NewError(acme.ErrorMalformedType, "'alg' field set to invalid algorithm '%s'", algorithm)
}
if keyID == "" {
return "", acme.NewError(acme.ErrorMalformedType, "'kid' field is required")
}
if nonce != "" {
return "", acme.NewError(acme.ErrorMalformedType, "'nonce' must not be present")
}
jwsURL, ok := header.ExtraHeaders["url"]
if !ok {
return "", acme.NewError(acme.ErrorMalformedType, "'url' field is required")
}
outerJWS, err := jwsFromContext(ctx)
if err != nil {
return "", acme.WrapErrorISE(err, "could not retrieve outer JWS from context")
}
if len(outerJWS.Signatures) != 1 {
return "", acme.NewError(acme.ErrorMalformedType, "outer JWS must have one signature")
}
outerJWSURL, ok := outerJWS.Signatures[0].Protected.ExtraHeaders["url"]
if !ok {
return "", acme.NewError(acme.ErrorMalformedType, "'url' field must be set in outer JWS")
}
if jwsURL != outerJWSURL {
return "", acme.NewError(acme.ErrorMalformedType, "'url' field is not the same value as the outer JWS")
}
return keyID, nil
}
================================================
FILE: acme/api/eab_test.go
================================================
package api
import (
"context"
"encoding/json"
"fmt"
"net/url"
"testing"
"time"
"github.com/pkg/errors"
"go.step.sm/crypto/jose"
"github.com/smallstep/assert"
"github.com/smallstep/certificates/acme"
)
func Test_keysAreEqual(t *testing.T) {
jwkX, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
jwkY, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
wrongJWK, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
wrongJWK.Key = struct{}{}
type args struct {
x *jose.JSONWebKey
y *jose.JSONWebKey
}
tests := []struct {
name string
args args
want bool
}{
{
name: "ok/nil",
args: args{
x: jwkX,
y: nil,
},
want: false,
},
{
name: "ok/equal",
args: args{
x: jwkX,
y: jwkX,
},
want: true,
},
{
name: "ok/not-equal",
args: args{
x: jwkX,
y: jwkY,
},
want: false,
},
{
name: "ok/wrong-key-type",
args: args{
x: wrongJWK,
y: jwkY,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := keysAreEqual(tt.args.x, tt.args.y); got != tt.want {
t.Errorf("keysAreEqual() = %v, want %v", got, tt.want)
}
})
}
}
func TestHandler_validateExternalAccountBinding(t *testing.T) {
acmeProv := newACMEProv(t)
escProvName := url.PathEscape(acmeProv.GetName())
baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"}
provID := acmeProv.GetID()
type test struct {
db acme.DB
ctx context.Context
nar *NewAccountRequest
eak *acme.ExternalAccountKey
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"ok/no-eab-required-but-provided": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
prov := newACMEProv(t)
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
return test{
db: &acme.MockDB{},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: nil,
}
},
"ok/eab": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
createdAt := time.Now()
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: createdAt,
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: createdAt,
},
err: nil,
}
},
"fail/acmeProvisionerFromContext": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
b, err := json.Marshal(nar)
assert.FatalError(t, err)
ctx := context.WithValue(context.Background(), payloadContextKey, &payloadInfo{value: b})
ctx = context.WithValue(ctx, jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, &fakeProvisioner{})
return test{
ctx: ctx,
err: acme.NewError(acme.ErrorServerInternalType, "could not load ACME provisioner from context: provisioner in context is not an ACME provisioner"),
}
},
"fail/parse-eab-jose": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
eab.Payload += "{}"
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
return test{
db: &acme.MockDB{},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewErrorISE("error parsing externalAccountBinding jws"),
}
},
"fail/validate-eab-jws-no-signatures": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
parsedJWS.Signatures = []jose.Signature{}
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorMalformedType, "outer JWS must have one signature"),
}
},
"fail/retrieve-eab-key-db-failure": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockError: errors.New("db failure"),
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewErrorISE("error retrieving external account key"),
}
},
"fail/db.GetExternalAccountKey-not-found": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return nil, acme.ErrNotFound
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewErrorISE("error retrieving external account key"),
}
},
"fail/db.GetExternalAccountKey-error": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return nil, errors.New("force")
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewErrorISE("error retrieving external account key"),
}
},
"fail/db.GetExternalAccountKey-nil": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return nil, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorUnauthorizedType, "the field 'kid' references an unknown key"),
}
},
"fail/db.GetExternalAccountKey-no-keybytes": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
createdAt := time.Now()
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
CreatedAt: createdAt,
AccountID: "some-account-id",
HmacKey: []byte{},
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorServerInternalType, "external account binding key with id 'eakID' does not have secret bytes"),
}
},
"fail/db.GetExternalAccountKey-wrong-provisioner": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockError: acme.NewError(acme.ErrorUnauthorizedType, "name of provisioner does not match provisioner for which the EAB key was created"),
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorUnauthorizedType, "the field 'kid' references an unknown key: name of provisioner does not match provisioner for which the EAB key was created"),
}
},
"fail/eab-already-bound": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
createdAt := time.Now()
boundAt := time.Now().Add(1 * time.Second)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
CreatedAt: createdAt,
AccountID: "some-account-id",
HmacKey: []byte{1, 3, 3, 7},
BoundAt: boundAt,
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorUnauthorizedType, "external account binding key with id '%s' was already bound to account '%s' on %s", "eakID", "some-account-id", boundAt),
}
},
"fail/eab-verify": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 2, 3, 4},
CreatedAt: time.Now(),
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewErrorISE("error verifying externalAccountBinding signature"),
}
},
"fail/eab-non-matching-keys": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
differentJWK, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(differentJWK, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, jwk)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: time.Now(),
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorUnauthorizedType, "keys in jws and eab payload do not match"),
}
},
"fail/no-jwk": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := acme.NewProvisionerContext(context.Background(), prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: time.Now(),
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorServerInternalType, "jwk expected in request context"),
}
},
"fail/nil-jwk": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
rawEABJWS, err := createRawEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal(rawEABJWS, &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
parsedJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
prov := newACMEProv(t)
prov.RequireEAB = true
ctx := context.WithValue(context.Background(), jwkContextKey, nil)
ctx = acme.NewProvisionerContext(ctx, prov)
ctx = context.WithValue(ctx, jwsContextKey, parsedJWS)
return test{
db: &acme.MockDB{
MockGetExternalAccountKey: func(ctx context.Context, provisionerName, keyID string) (*acme.ExternalAccountKey, error) {
return &acme.ExternalAccountKey{
ID: "eakID",
ProvisionerID: provID,
Reference: "testeak",
HmacKey: []byte{1, 3, 3, 7},
CreatedAt: time.Now(),
}, nil
},
},
ctx: ctx,
nar: &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
},
eak: nil,
err: acme.NewError(acme.ErrorServerInternalType, "jwk expected in request context"),
}
},
}
for name, run := range tests {
tc := run(t)
t.Run(name, func(t *testing.T) {
ctx := acme.NewDatabaseContext(tc.ctx, tc.db)
got, err := validateExternalAccountBinding(ctx, tc.nar)
wantErr := tc.err != nil
gotErr := err != nil
if wantErr != gotErr {
t.Errorf("Handler.validateExternalAccountBinding() error = %v, want %v", err, tc.err)
}
if wantErr {
assert.NotNil(t, err)
assert.Type(t, &acme.Error{}, err)
var ae *acme.Error
if assert.True(t, errors.As(err, &ae)) {
assert.Equals(t, ae.Type, tc.err.Type)
assert.Equals(t, ae.Status, tc.err.Status)
assert.HasPrefix(t, ae.Err.Error(), tc.err.Err.Error())
assert.Equals(t, ae.Detail, tc.err.Detail)
assert.Equals(t, ae.Subproblems, tc.err.Subproblems)
}
} else {
if got == nil {
assert.Nil(t, tc.eak)
} else {
assert.NotNil(t, tc.eak)
assert.Equals(t, got.ID, tc.eak.ID)
assert.Equals(t, got.HmacKey, tc.eak.HmacKey)
assert.Equals(t, got.ProvisionerID, tc.eak.ProvisionerID)
assert.Equals(t, got.Reference, tc.eak.Reference)
assert.Equals(t, got.CreatedAt, tc.eak.CreatedAt)
assert.Equals(t, got.AccountID, tc.eak.AccountID)
assert.Equals(t, got.BoundAt, tc.eak.BoundAt)
}
}
})
}
}
func Test_validateEABJWS(t *testing.T) {
acmeProv := newACMEProv(t)
escProvName := url.PathEscape(acmeProv.GetName())
baseURL := &url.URL{Scheme: "https", Host: "test.ca.smallstep.com"}
type test struct {
ctx context.Context
jws *jose.JSONWebSignature
keyID string
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/nil-jws": func(t *testing.T) test {
return test{
jws: nil,
err: acme.NewErrorISE("no JWS provided"),
}
},
"fail/invalid-number-of-signatures": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eabJWS.Signatures = append(eabJWS.Signatures, jose.Signature{})
return test{
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "JWS must have one signature"),
}
},
"fail/invalid-algorithm": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eabJWS.Signatures[0].Protected.Algorithm = "HS42"
return test{
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "'alg' field set to invalid algorithm 'HS42'"),
}
},
"fail/kid-not-set": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eabJWS.Signatures[0].Protected.KeyID = ""
return test{
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "'kid' field is required"),
}
},
"fail/nonce-not-empty": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
eabJWS.Signatures[0].Protected.Nonce = "some-bogus-nonce"
return test{
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "'nonce' must not be present"),
}
},
"fail/url-not-set": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
delete(eabJWS.Signatures[0].Protected.ExtraHeaders, "url")
return test{
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "'url' field is required"),
}
},
"fail/no-outer-jws": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
ctx := context.WithValue(context.TODO(), jwsContextKey, nil)
return test{
ctx: ctx,
jws: eabJWS,
err: acme.NewErrorISE("could not retrieve outer JWS from context"),
}
},
"fail/outer-jws-multiple-signatures": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
rawEABJWS := eabJWS.FullSerialize()
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal([]byte(rawEABJWS), &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
outerJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
outerJWS.Signatures = append(outerJWS.Signatures, jose.Signature{})
ctx := context.WithValue(context.TODO(), jwsContextKey, outerJWS)
return test{
ctx: ctx,
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "outer JWS must have one signature"),
}
},
"fail/outer-jws-no-url": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
rawEABJWS := eabJWS.FullSerialize()
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal([]byte(rawEABJWS), &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
outerJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
ctx := context.WithValue(context.TODO(), jwsContextKey, outerJWS)
return test{
ctx: ctx,
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "'url' field must be set in outer JWS"),
}
},
"fail/outer-jws-with-different-url": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
rawEABJWS := eabJWS.FullSerialize()
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal([]byte(rawEABJWS), &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", "this-is-not-the-same-url-as-in-the-eab-jws")
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
outerJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
ctx := context.WithValue(context.TODO(), jwsContextKey, outerJWS)
return test{
ctx: ctx,
jws: eabJWS,
err: acme.NewError(acme.ErrorMalformedType, "'url' field is not the same value as the outer JWS"),
}
},
"ok": func(t *testing.T) test {
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
assert.FatalError(t, err)
url := fmt.Sprintf("%s/acme/%s/account/new-account", baseURL.String(), escProvName)
eabJWS, err := createEABJWS(jwk, []byte{1, 3, 3, 7}, "eakID", url)
assert.FatalError(t, err)
rawEABJWS := eabJWS.FullSerialize()
assert.FatalError(t, err)
eab := &ExternalAccountBinding{}
err = json.Unmarshal([]byte(rawEABJWS), &eab)
assert.FatalError(t, err)
nar := &NewAccountRequest{
Contact: []string{"foo", "bar"},
ExternalAccountBinding: eab,
}
payloadBytes, err := json.Marshal(nar)
assert.FatalError(t, err)
so := new(jose.SignerOptions)
so.WithHeader("alg", jose.SignatureAlgorithm(jwk.Algorithm))
so.WithHeader("url", url)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(jwk.Algorithm),
Key: jwk.Key,
}, so)
assert.FatalError(t, err)
jws, err := signer.Sign(payloadBytes)
assert.FatalError(t, err)
raw, err := jws.CompactSerialize()
assert.FatalError(t, err)
outerJWS, err := jose.ParseJWS(raw)
assert.FatalError(t, err)
ctx := context.WithValue(context.TODO(), jwsContextKey, outerJWS)
return test{
ctx: ctx,
jws: eabJWS,
keyID: "eakID",
err: nil,
}
},
}
for name, prep := range tests {
tc := prep(t)
t.Run(name, func(t *testing.T) {
keyID, err := validateEABJWS(tc.ctx, tc.jws)
wantErr := tc.err != nil
gotErr := err != nil
if wantErr != gotErr {
t.Errorf("validateEABJWS() error = %v, want %v", err, tc.err)
}
if wantErr {
assert.NotNil(t, err)
assert.Equals(t, tc.err.Type, err.Type)
assert.Equals(t, tc.err.Status, err.Status)
assert.HasPrefix(t, err.Err.Error(), tc.err.Err.Error())
assert.Equals(t, tc.err.Detail, err.Detail)
assert.Equals(t, tc.err.Subproblems, err.Subproblems)
} else {
assert.Nil(t, err)
assert.Equals(t, tc.keyID, keyID)
}
})
}
}
================================================
FILE: acme/api/handler.go
================================================
package api
import (
"context"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"net/http"
"time"
"github.com/go-chi/chi/v5"
"github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner"
)
func link(url, typ string) string {
return fmt.Sprintf("<%s>;rel=%q", url, typ)
}
// Clock that returns time in UTC rounded to seconds.
type Clock struct{}
// Now returns the UTC time rounded to seconds.
func (c *Clock) Now() time.Time {
return time.Now().UTC().Truncate(time.Second)
}
var clock Clock
type payloadInfo struct {
value []byte
isPostAsGet bool
isEmptyJSON bool
}
// HandlerOptions required to create a new ACME API request handler.
type HandlerOptions struct {
// DB storage backend that implements the acme.DB interface.
//
// Deprecated: use acme.NewContex(context.Context, acme.DB)
DB acme.DB
// CA is the certificate authority interface.
//
// Deprecated: use authority.NewContext(context.Context, *authority.Authority)
CA acme.CertificateAuthority
// Backdate is the duration that the CA will subtract from the current time
// to set the NotBefore in the certificate.
Backdate provisioner.Duration
// DNS the host used to generate accurate ACME links. By default the authority
// will use the Host from the request, so this value will only be used if
// request.Host is empty.
DNS string
// Prefix is a URL path prefix under which the ACME api is served. This
// prefix is required to generate accurate ACME links.
// E.g. https://ca.smallstep.com/acme/my-acme-provisioner/new-account --
// "acme" is the prefix from which the ACME api is accessed.
Prefix string
// PrerequisitesChecker checks if all prerequisites for serving ACME are
// met by the CA configuration.
PrerequisitesChecker func(ctx context.Context) (bool, error)
}
var mustAuthority = func(ctx context.Context) acme.CertificateAuthority {
return authority.MustFromContext(ctx)
}
// handler is the ACME API request handler.
type handler struct {
opts *HandlerOptions
}
// Route traffic and implement the Router interface. For backward compatibility
// this route adds will add a new middleware that will set the ACME components
// on the context.
//
// Note: this method is deprecated in step-ca, other applications can still use
// this to support ACME, but the recommendation is to use use
// api.Route(api.Router) and acme.NewContext() instead.
func (h *handler) Route(r api.Router) {
client := acme.NewClient()
linker := acme.NewLinker(h.opts.DNS, h.opts.Prefix)
route(r, func(next nextHTTP) nextHTTP {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
if ca, ok := h.opts.CA.(*authority.Authority); ok && ca != nil {
ctx = authority.NewContext(ctx, ca)
}
ctx = acme.NewContext(ctx, h.opts.DB, client, linker, h.opts.PrerequisitesChecker)
next(w, r.WithContext(ctx))
}
})
}
// NewHandler returns a new ACME API handler.
//
// Note: this method is deprecated in step-ca, other applications can still use
// this to support ACME, but the recommendation is to use use
// api.Route(api.Router) and acme.NewContext() instead.
func NewHandler(opts HandlerOptions) api.RouterHandler {
return &handler{
opts: &opts,
}
}
// Route traffic and implement the Router interface. This method requires that
// all the acme components, authority, db, client, linker, and prerequisite
// checker to be present in the context.
func Route(r api.Router) {
route(r, nil)
}
func route(r api.Router, middleware func(next nextHTTP) nextHTTP) {
commonMiddleware := func(next nextHTTP) nextHTTP {
handler := func(w http.ResponseWriter, r *http.Request) {
// Linker middleware gets the provisioner and current url from the
// request and sets them in the context.
linker := acme.MustLinkerFromContext(r.Context())
linker.Middleware(http.HandlerFunc(checkPrerequisites(next))).ServeHTTP(w, r)
}
if middleware != nil {
handler = middleware(handler)
}
return handler
}
validatingMiddleware := func(next nextHTTP) nextHTTP {
return commonMiddleware(addNonce(addDirLink(verifyContentType(parseJWS(validateJWS(next))))))
}
extractPayloadByJWK := func(next nextHTTP) nextHTTP {
return validatingMiddleware(extractJWK(verifyAndExtractJWSPayload(next)))
}
extractPayloadByKid := func(next nextHTTP) nextHTTP {
return validatingMiddleware(lookupJWK(verifyAndExtractJWSPayload(next)))
}
extractPayloadByKidOrJWK := func(next nextHTTP) nextHTTP {
return validatingMiddleware(extractOrLookupJWK(verifyAndExtractJWSPayload(next)))
}
getPath := acme.GetUnescapedPathSuffix
// Standard ACME API
r.MethodFunc("GET", getPath(acme.NewNonceLinkType, "{provisionerID}"),
commonMiddleware(addNonce(addDirLink(GetNonce))))
r.MethodFunc("HEAD", getPath(acme.NewNonceLinkType, "{provisionerID}"),
commonMiddleware(addNonce(addDirLink(GetNonce))))
r.MethodFunc("GET", getPath(acme.DirectoryLinkType, "{provisionerID}"),
commonMiddleware(GetDirectory))
r.MethodFunc("HEAD", getPath(acme.DirectoryLinkType, "{provisionerID}"),
commonMiddleware(GetDirectory))
r.MethodFunc("POST", getPath(acme.NewAccountLinkType, "{provisionerID}"),
extractPayloadByJWK(NewAccount))
r.MethodFunc("POST", getPath(acme.AccountLinkType, "{provisionerID}", "{accID}"),
extractPayloadByKid(GetOrUpdateAccount))
r.MethodFunc("POST", getPath(acme.KeyChangeLinkType, "{provisionerID}", "{accID}"),
extractPayloadByKid(NotImplemented))
r.MethodFunc("POST", getPath(acme.NewOrderLinkType, "{provisionerID}"),
extractPayloadByKid(NewOrder))
r.MethodFunc("POST", getPath(acme.OrderLinkType, "{provisionerID}", "{ordID}"),
extractPayloadByKid(isPostAsGet(GetOrder)))
r.MethodFunc("POST", getPath(acme.OrdersByAccountLinkType, "{provisionerID}", "{accID}"),
extractPayloadByKid(isPostAsGet(GetOrdersByAccountID)))
r.MethodFunc("POST", getPath(acme.FinalizeLinkType, "{provisionerID}", "{ordID}"),
extractPayloadByKid(FinalizeOrder))
r.MethodFunc("POST", getPath(acme.AuthzLinkType, "{provisionerID}", "{authzID}"),
extractPayloadByKid(isPostAsGet(GetAuthorization)))
r.MethodFunc("POST", getPath(acme.ChallengeLinkType, "{provisionerID}", "{authzID}", "{chID}"),
extractPayloadByKid(GetChallenge))
r.MethodFunc("POST", getPath(acme.CertificateLinkType, "{provisionerID}", "{certID}"),
extractPayloadByKid(isPostAsGet(GetCertificate)))
r.MethodFunc("POST", getPath(acme.RevokeCertLinkType, "{provisionerID}"),
extractPayloadByKidOrJWK(RevokeCert))
}
// GetNonce just sets the right header since a Nonce is added to each response
// by middleware by default.
func GetNonce(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusNoContent)
}
}
type Meta struct {
TermsOfService string `json:"termsOfService,omitempty"`
Website string `json:"website,omitempty"`
CaaIdentities []string `json:"caaIdentities,omitempty"`
ExternalAccountRequired bool `json:"externalAccountRequired,omitempty"`
}
// Directory represents an ACME directory for configuring clients.
type Directory struct {
NewNonce string `json:"newNonce"`
NewAccount string `json:"newAccount"`
NewOrder string `json:"newOrder"`
RevokeCert string `json:"revokeCert"`
KeyChange string `json:"keyChange"`
Meta *Meta `json:"meta,omitempty"`
}
// ToLog enables response logging for the Directory type.
func (d *Directory) ToLog() (interface{}, error) {
b, err := json.Marshal(d)
if err != nil {
return nil, acme.WrapErrorISE(err, "error marshaling directory for logging")
}
return string(b), nil
}
// GetDirectory is the ACME resource for returning a directory configuration
// for client configuration.
func GetDirectory(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
acmeProv, err := acmeProvisionerFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
linker := acme.MustLinkerFromContext(ctx)
render.JSON(w, r, &Directory{
NewNonce: linker.GetLink(ctx, acme.NewNonceLinkType),
NewAccount: linker.GetLink(ctx, acme.NewAccountLinkType),
NewOrder: linker.GetLink(ctx, acme.NewOrderLinkType),
RevokeCert: linker.GetLink(ctx, acme.RevokeCertLinkType),
KeyChange: linker.GetLink(ctx, acme.KeyChangeLinkType),
Meta: createMetaObject(acmeProv),
})
}
// createMetaObject creates a Meta object if the ACME provisioner
// has one or more properties that are written in the ACME directory output.
// It returns nil if none of the properties are set.
func createMetaObject(p *provisioner.ACME) *Meta {
if shouldAddMetaObject(p) {
return &Meta{
TermsOfService: p.TermsOfService,
Website: p.Website,
CaaIdentities: p.CaaIdentities,
ExternalAccountRequired: p.RequireEAB,
}
}
return nil
}
// shouldAddMetaObject returns whether or not the ACME provisioner
// has properties configured that must be added to the ACME directory object.
func shouldAddMetaObject(p *provisioner.ACME) bool {
switch {
case p.TermsOfService != "":
return true
case p.Website != "":
return true
case len(p.CaaIdentities) > 0:
return true
case p.RequireEAB:
return true
default:
return false
}
}
// NotImplemented returns a 501 and is generally a placeholder for functionality which
// MAY be added at some point in the future but is not in any way a guarantee of such.
func NotImplemented(w http.ResponseWriter, r *http.Request) {
render.Error(w, r, acme.NewError(acme.ErrorNotImplementedType, "this API is not implemented"))
}
// GetAuthorization ACME api for retrieving an Authz.
func GetAuthorization(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
db := acme.MustDatabaseFromContext(ctx)
linker := acme.MustLinkerFromContext(ctx)
acc, err := accountFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
az, err := db.GetAuthorization(ctx, chi.URLParam(r, "authzID"))
if err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error retrieving authorization"))
return
}
if acc.ID != az.AccountID {
render.Error(w, r, acme.NewError(acme.ErrorUnauthorizedType,
"account '%s' does not own authorization '%s'", acc.ID, az.ID))
return
}
if err = az.UpdateStatus(ctx, db); err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error updating authorization status"))
return
}
linker.LinkAuthorization(ctx, az)
w.Header().Set("Location", linker.GetLink(ctx, acme.AuthzLinkType, az.ID))
render.JSON(w, r, az)
}
// GetChallenge ACME api for retrieving a Challenge.
func GetChallenge(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
db := acme.MustDatabaseFromContext(ctx)
linker := acme.MustLinkerFromContext(ctx)
acc, err := accountFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
payload, err := payloadFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
// NOTE: We should be checking that the request is either a POST-as-GET, or
// that for all challenges except for device-attest-01, the payload is an
// empty JSON block ({}). However, older ACME clients still send a vestigial
// body (rather than an empty JSON block) and strict enforcement would
// render these clients broken.
azID := chi.URLParam(r, "authzID")
ch, err := db.GetChallenge(ctx, chi.URLParam(r, "chID"), azID)
if err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error retrieving challenge"))
return
}
ch.AuthorizationID = azID
if acc.ID != ch.AccountID {
render.Error(w, r, acme.NewError(acme.ErrorUnauthorizedType,
"account '%s' does not own challenge '%s'", acc.ID, ch.ID))
return
}
jwk, err := jwkFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
if err = ch.Validate(ctx, db, jwk, payload.value); err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error validating challenge"))
return
}
linker.LinkChallenge(ctx, ch, azID)
w.Header().Add("Link", link(linker.GetLink(ctx, acme.AuthzLinkType, azID), "up"))
w.Header().Set("Location", linker.GetLink(ctx, acme.ChallengeLinkType, azID, ch.ID))
render.JSON(w, r, ch)
}
// GetCertificate ACME api for retrieving a Certificate.
func GetCertificate(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
db := acme.MustDatabaseFromContext(ctx)
acc, err := accountFromContext(ctx)
if err != nil {
render.Error(w, r, err)
return
}
certID := chi.URLParam(r, "certID")
cert, err := db.GetCertificate(ctx, certID)
if err != nil {
render.Error(w, r, acme.WrapErrorISE(err, "error retrieving certificate"))
return
}
if cert.AccountID != acc.ID {
render.Error(w, r, acme.NewError(acme.ErrorUnauthorizedType,
"account '%s' does not own certificate '%s'", acc.ID, certID))
return
}
var certBytes []byte
for _, c := range append([]*x509.Certificate{cert.Leaf}, cert.Intermediates...) {
certBytes = append(certBytes, pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: c.Raw,
})...)
}
api.LogCertificate(w, cert.Leaf)
w.Header().Set("Content-Type", "application/pem-certificate-chain")
w.Write(certBytes)
}
================================================
FILE: acme/api/handler_test.go
================================================
package api
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"
"github.com/go-chi/chi/v5"
"github.com/google/go-cmp/cmp"
"github.com/pkg/errors"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/pemutil"
"github.com/smallstep/assert"
"github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/authority/provisioner"
)
type mockClient struct {
get func(url string) (*http.Response, error)
lookupTxt func(name string) ([]string, error)
tlsDial func(network, addr string, config *tls.Config) (*tls.Conn, error)
}
func (m *mockClient) Get(u string) (*http.Response, error) { return m.get(u) }
func (m *mockClient) LookupTxt(name string) ([]string, error) { return m.lookupTxt(name) }
func (m *mockClient) TLSDial(network, addr string, config *tls.Config) (*tls.Conn, error) {
return m.tlsDial(network, addr, config)
}
func mockMustAuthority(t *testing.T, a acme.CertificateAuthority) {
t.Helper()
fn := mustAuthority
t.Cleanup(func() {
mustAuthority = fn
})
mustAuthority = func(ctx context.Context) acme.CertificateAuthority {
return a
}
}
func TestHandler_GetNonce(t *testing.T) {
tests := []struct {
name string
statusCode int
}{
{"GET", 204},
{"HEAD", 200},
}
// Request with chi context
req := httptest.NewRequest("GET", "http://ca.smallstep.com/nonce", http.NoBody)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// h := &Handler{}
w := httptest.NewRecorder()
req.Method = tt.name
GetNonce(w, req)
res := w.Result()
if res.StatusCode != tt.statusCode {
t.Errorf("Handler.GetNonce StatusCode = %d, wants %d", res.StatusCode, tt.statusCode)
}
})
}
}
func TestHandler_GetDirectory(t *testing.T) {
linker := acme.NewLinker("ca.smallstep.com", "acme")
_ = linker
type test struct {
ctx context.Context
statusCode int
dir Directory
err *acme.Error
}
var tests = map[string]func(t *testing.T) test{
"fail/no-provisioner": func(t *testing.T) test {
return test{
ctx: context.Background(),
statusCode: 500,
err: acme.NewErrorISE("provisioner is not in context"),
}
},
"fail/different-provisioner": func(t *testing.T) test {
ctx := acme.NewProvisionerContext(context.Background(), &fakeProvisioner{})
return test{
ctx: ctx,
statusCode: 500,
err: acme.NewErrorISE(
gitextract_pt61h5ml/
├── .VERSION
├── .dockerignore
├── .gitattributes
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.yml
│ │ ├── config.yml
│ │ ├── documentation-request.md
│ │ └── enhancement.md
│ ├── PULL_REQUEST_TEMPLATE
│ ├── dependabot.yml
│ ├── workflows/
│ │ ├── actionci.yml
│ │ ├── ci.yml
│ │ ├── code-scan-cron.yml
│ │ ├── dependabot-auto-merge.yml
│ │ ├── publish-packages.yml
│ │ ├── release.yml
│ │ └── triage.yml
│ └── zizmor.yml
├── .gitignore
├── .goreleaser.yml
├── .version.sh
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── acme/
│ ├── account.go
│ ├── account_test.go
│ ├── api/
│ │ ├── account.go
│ │ ├── account_test.go
│ │ ├── eab.go
│ │ ├── eab_test.go
│ │ ├── handler.go
│ │ ├── handler_test.go
│ │ ├── middleware.go
│ │ ├── middleware_test.go
│ │ ├── order.go
│ │ ├── order_test.go
│ │ ├── revoke.go
│ │ ├── revoke_test.go
│ │ └── wire_integration_test.go
│ ├── authorization.go
│ ├── authorization_test.go
│ ├── certificate.go
│ ├── challenge.go
│ ├── challenge_test.go
│ ├── challenge_tpmsimulator_test.go
│ ├── challenge_wire_test.go
│ ├── client.go
│ ├── common.go
│ ├── db/
│ │ └── nosql/
│ │ ├── account.go
│ │ ├── account_test.go
│ │ ├── authz.go
│ │ ├── authz_test.go
│ │ ├── certificate.go
│ │ ├── certificate_test.go
│ │ ├── challenge.go
│ │ ├── challenge_test.go
│ │ ├── eab.go
│ │ ├── eab_test.go
│ │ ├── nonce.go
│ │ ├── nonce_test.go
│ │ ├── nosql.go
│ │ ├── nosql_test.go
│ │ ├── order.go
│ │ ├── order_test.go
│ │ ├── wire.go
│ │ └── wire_test.go
│ ├── db.go
│ ├── db_test.go
│ ├── errors.go
│ ├── errors_test.go
│ ├── linker.go
│ ├── linker_test.go
│ ├── nonce.go
│ ├── order.go
│ ├── order_test.go
│ ├── status.go
│ └── wire/
│ ├── id.go
│ └── id_test.go
├── api/
│ ├── api.go
│ ├── api_test.go
│ ├── crl.go
│ ├── crl_test.go
│ ├── log/
│ │ ├── log.go
│ │ └── log_test.go
│ ├── models/
│ │ └── scep.go
│ ├── read/
│ │ ├── read.go
│ │ └── read_test.go
│ ├── rekey.go
│ ├── render/
│ │ ├── render.go
│ │ └── render_test.go
│ ├── renew.go
│ ├── revoke.go
│ ├── revoke_test.go
│ ├── sign.go
│ ├── ssh.go
│ ├── sshRekey.go
│ ├── sshRenew.go
│ ├── sshRevoke.go
│ └── ssh_test.go
├── authority/
│ ├── admin/
│ │ ├── api/
│ │ │ ├── acme.go
│ │ │ ├── acme_test.go
│ │ │ ├── admin.go
│ │ │ ├── admin_test.go
│ │ │ ├── handler.go
│ │ │ ├── middleware.go
│ │ │ ├── middleware_test.go
│ │ │ ├── policy.go
│ │ │ ├── policy_test.go
│ │ │ ├── provisioner.go
│ │ │ ├── provisioner_test.go
│ │ │ ├── webhook.go
│ │ │ └── webhook_test.go
│ │ ├── db/
│ │ │ └── nosql/
│ │ │ ├── admin.go
│ │ │ ├── admin_test.go
│ │ │ ├── nosql.go
│ │ │ ├── policy.go
│ │ │ ├── policy_test.go
│ │ │ ├── provisioner.go
│ │ │ └── provisioner_test.go
│ │ ├── db.go
│ │ └── errors.go
│ ├── administrator/
│ │ └── collection.go
│ ├── admins.go
│ ├── authority.go
│ ├── authority_test.go
│ ├── authorize.go
│ ├── authorize_test.go
│ ├── config/
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── ssh.go
│ │ ├── ssh_test.go
│ │ ├── tls_options.go
│ │ ├── tls_options_test.go
│ │ ├── types.go
│ │ └── types_test.go
│ ├── config.go
│ ├── export.go
│ ├── http_client.go
│ ├── http_client_test.go
│ ├── internal/
│ │ └── constraints/
│ │ ├── constraints.go
│ │ ├── constraints_test.go
│ │ └── verify.go
│ ├── linkedca.go
│ ├── meter.go
│ ├── options.go
│ ├── policy/
│ │ ├── engine.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── policy.go
│ │ └── policy_test.go
│ ├── policy.go
│ ├── policy_test.go
│ ├── poolhttp/
│ │ ├── poolhttp.go
│ │ └── poolhttp_test.go
│ ├── provisioner/
│ │ ├── acme.go
│ │ ├── acme_118_test.go
│ │ ├── acme_119_test.go
│ │ ├── acme_test.go
│ │ ├── aws.go
│ │ ├── aws_certificates.pem
│ │ ├── aws_test.go
│ │ ├── azure.go
│ │ ├── azure_test.go
│ │ ├── claims.go
│ │ ├── claims_test.go
│ │ ├── collection.go
│ │ ├── collection_test.go
│ │ ├── controller.go
│ │ ├── controller_test.go
│ │ ├── duration.go
│ │ ├── duration_test.go
│ │ ├── extension.go
│ │ ├── extension_test.go
│ │ ├── gcp/
│ │ │ ├── projectvalidator.go
│ │ │ └── projectvalidator_test.go
│ │ ├── gcp.go
│ │ ├── gcp_test.go
│ │ ├── jwk.go
│ │ ├── jwk_test.go
│ │ ├── k8sSA.go
│ │ ├── k8sSA_test.go
│ │ ├── keystore.go
│ │ ├── keystore_test.go
│ │ ├── method.go
│ │ ├── nebula.go
│ │ ├── nebula_test.go
│ │ ├── noop.go
│ │ ├── noop_test.go
│ │ ├── oidc.go
│ │ ├── oidc_test.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── policy.go
│ │ ├── provisioner.go
│ │ ├── provisioner_test.go
│ │ ├── scep.go
│ │ ├── scep_test.go
│ │ ├── sign_options.go
│ │ ├── sign_options_test.go
│ │ ├── sign_ssh_options.go
│ │ ├── sign_ssh_options_test.go
│ │ ├── ssh_options.go
│ │ ├── ssh_options_test.go
│ │ ├── ssh_test.go
│ │ ├── sshpop.go
│ │ ├── sshpop_test.go
│ │ ├── testdata/
│ │ │ ├── certs/
│ │ │ │ ├── apple-att-ca.crt
│ │ │ │ ├── aws-test.crt
│ │ │ │ ├── aws.crt
│ │ │ │ ├── bad-extension.crt
│ │ │ │ ├── bar.pub
│ │ │ │ ├── ecdsa.csr
│ │ │ │ ├── ed25519.csr
│ │ │ │ ├── foo.crt
│ │ │ │ ├── foo.pub
│ │ │ │ ├── good-extension.crt
│ │ │ │ ├── root_ca.crt
│ │ │ │ ├── rsa.csr
│ │ │ │ ├── short-rsa.csr
│ │ │ │ ├── ssh_host_ca_key.pub
│ │ │ │ ├── ssh_user_ca_key.pub
│ │ │ │ ├── x5c-leaf.crt
│ │ │ │ └── yubico-piv-ca.crt
│ │ │ ├── secrets/
│ │ │ │ ├── bar.priv
│ │ │ │ ├── bar_host_ssh_key
│ │ │ │ ├── ecdsa.key
│ │ │ │ ├── ed25519.key
│ │ │ │ ├── foo.key
│ │ │ │ ├── foo.priv
│ │ │ │ ├── foo_user_ssh_key
│ │ │ │ ├── rsa.key
│ │ │ │ ├── ssh_host_ca_key
│ │ │ │ ├── ssh_user_ca_key
│ │ │ │ └── x5c-leaf.key
│ │ │ └── templates/
│ │ │ └── cr.tpl
│ │ ├── timeduration.go
│ │ ├── timeduration_test.go
│ │ ├── utils_test.go
│ │ ├── webhook.go
│ │ ├── webhook_test.go
│ │ ├── wire/
│ │ │ ├── dpop_options.go
│ │ │ ├── dpop_options_test.go
│ │ │ ├── oidc_options.go
│ │ │ ├── oidc_options_test.go
│ │ │ ├── wire_options.go
│ │ │ └── wire_options_test.go
│ │ ├── x5c.go
│ │ └── x5c_test.go
│ ├── provisioners.go
│ ├── provisioners_test.go
│ ├── root.go
│ ├── root_test.go
│ ├── ssh.go
│ ├── ssh_test.go
│ ├── testdata/
│ │ ├── certs/
│ │ │ ├── badsig.csr
│ │ │ ├── foo.crt
│ │ │ ├── foo.csr
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── provisioner-not-found.crt
│ │ │ ├── renew-disabled.crt
│ │ │ ├── root_ca.crt
│ │ │ ├── ssh_host_ca_key.pub
│ │ │ └── ssh_user_ca_key.pub
│ │ ├── scep/
│ │ │ ├── intermediate.crt
│ │ │ ├── intermediate.key
│ │ │ ├── root.crt
│ │ │ └── root.key
│ │ ├── secrets/
│ │ │ ├── foo.key
│ │ │ ├── intermediate_ca_key
│ │ │ ├── max_priv.jwk
│ │ │ ├── max_pub.jwk
│ │ │ ├── provisioner-not-found.key
│ │ │ ├── renew-disabled.key
│ │ │ ├── ssh_host_ca_key
│ │ │ ├── ssh_user_ca_key
│ │ │ ├── step_cli_key
│ │ │ ├── step_cli_key.public
│ │ │ ├── step_cli_key_priv.jwk
│ │ │ └── step_cli_key_pub.jwk
│ │ └── templates/
│ │ ├── badjsonsyntax.tpl
│ │ ├── badjsonvalue.tpl
│ │ ├── ca.tpl
│ │ ├── config.tpl
│ │ ├── error.tpl
│ │ ├── fail.tpl
│ │ ├── include.tpl
│ │ ├── known_hosts.tpl
│ │ ├── sshd_config.tpl
│ │ └── step_includes.tpl
│ ├── tls.go
│ ├── tls_test.go
│ ├── version.go
│ ├── webhook.go
│ └── webhook_test.go
├── autocert/
│ └── README.md
├── ca/
│ ├── acmeClient.go
│ ├── acmeClient_test.go
│ ├── adminClient.go
│ ├── bootstrap.go
│ ├── bootstrap_test.go
│ ├── ca.go
│ ├── ca_test.go
│ ├── client/
│ │ └── requestid.go
│ ├── client.go
│ ├── client_test.go
│ ├── identity/
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── identity.go
│ │ ├── identity_test.go
│ │ └── testdata/
│ │ ├── certs/
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── root_ca.crt
│ │ │ └── server.crt
│ │ ├── config/
│ │ │ ├── badIdentity.json
│ │ │ ├── badca.json
│ │ │ ├── badroot.json
│ │ │ ├── ca.json
│ │ │ ├── defaults.json
│ │ │ ├── fail.json
│ │ │ ├── identity.json
│ │ │ └── tunnel.json
│ │ ├── identity/
│ │ │ ├── expired.crt
│ │ │ ├── identity.crt
│ │ │ ├── identity_key
│ │ │ └── not_before.crt
│ │ └── secrets/
│ │ ├── intermediate_ca_key
│ │ ├── root_ca_key
│ │ └── server_key
│ ├── mutable_tls_config.go
│ ├── provisioner.go
│ ├── provisioner_test.go
│ ├── renew.go
│ ├── signal.go
│ ├── testdata/
│ │ ├── ca.json
│ │ ├── federated-ca.json
│ │ ├── rotate-ca-0.json
│ │ ├── rotate-ca-1.json
│ │ ├── rotate-ca-2.json
│ │ ├── rotate-ca-3.json
│ │ ├── rotated/
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── intermediate_ca_key
│ │ │ ├── root_ca.crt
│ │ │ └── root_ca_key
│ │ ├── rsaca.json
│ │ └── secrets/
│ │ ├── federated_ca.crt
│ │ ├── intermediate_ca.crt
│ │ ├── intermediate_ca_key
│ │ ├── ott_key
│ │ ├── ott_key.public
│ │ ├── ott_mariano_priv.jwk
│ │ ├── ott_mariano_pub.jwk
│ │ ├── root_ca.crt
│ │ ├── root_ca_key
│ │ ├── rsa_intermediate_ca.crt
│ │ ├── rsa_intermediate_ca_key
│ │ ├── rsa_root_ca.crt
│ │ ├── rsa_root_ca_key
│ │ ├── step_cli_key
│ │ ├── step_cli_key.public
│ │ ├── step_cli_key_priv.jwk
│ │ └── step_cli_key_pub.jwk
│ ├── tls.go
│ ├── tls_options.go
│ ├── tls_options_test.go
│ └── tls_test.go
├── cas/
│ ├── apiv1/
│ │ ├── extension.go
│ │ ├── extension_test.go
│ │ ├── options.go
│ │ ├── options_test.go
│ │ ├── registry.go
│ │ ├── registry_test.go
│ │ ├── requests.go
│ │ ├── services.go
│ │ └── services_test.go
│ ├── cas.go
│ ├── cas_test.go
│ ├── cloudcas/
│ │ ├── certificate.go
│ │ ├── certificate_test.go
│ │ ├── cloudcas.go
│ │ ├── cloudcas_test.go
│ │ ├── mock_client_test.go
│ │ └── mock_operation_server_test.go
│ ├── softcas/
│ │ ├── softcas.go
│ │ └── softcas_test.go
│ ├── stepcas/
│ │ ├── issuer.go
│ │ ├── issuer_test.go
│ │ ├── jwk_issuer.go
│ │ ├── jwk_issuer_test.go
│ │ ├── stepcas.go
│ │ ├── stepcas_test.go
│ │ ├── x5c_issuer.go
│ │ └── x5c_issuer_test.go
│ └── vaultcas/
│ ├── auth/
│ │ ├── approle/
│ │ │ ├── approle.go
│ │ │ └── approle_test.go
│ │ ├── aws/
│ │ │ ├── aws.go
│ │ │ └── aws_test.go
│ │ └── kubernetes/
│ │ ├── kubernetes.go
│ │ ├── kubernetes_test.go
│ │ └── token
│ ├── vaultcas.go
│ └── vaultcas_test.go
├── cmd/
│ └── step-ca/
│ └── main.go
├── commands/
│ ├── app.go
│ ├── export.go
│ └── onboard.go
├── cosign.pub
├── db/
│ ├── db.go
│ ├── db_test.go
│ ├── simple.go
│ └── simple_test.go
├── debian/
│ └── copyright
├── docker/
│ ├── Dockerfile
│ ├── Dockerfile.hsm
│ └── entrypoint.sh
├── errs/
│ ├── error.go
│ └── errors_test.go
├── examples/
│ ├── README.md
│ ├── ansible/
│ │ ├── smallstep-certs/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ ├── smallstep-install/
│ │ │ ├── defaults/
│ │ │ │ └── main.yml
│ │ │ └── tasks/
│ │ │ └── main.yml
│ │ └── smallstep-ssh/
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ └── tasks/
│ │ └── main.yml
│ ├── basic-client/
│ │ └── client.go
│ ├── basic-federation/
│ │ ├── client/
│ │ │ └── main.go
│ │ ├── pki/
│ │ │ ├── cloud/
│ │ │ │ ├── certs/
│ │ │ │ │ ├── intermediate_ca.crt
│ │ │ │ │ ├── kubernetes_root_ca.crt
│ │ │ │ │ └── root_ca.crt
│ │ │ │ ├── config/
│ │ │ │ │ ├── ca.federated.json
│ │ │ │ │ └── ca.json
│ │ │ │ └── secrets/
│ │ │ │ ├── intermediate_ca_key
│ │ │ │ └── root_ca_key
│ │ │ └── kubernetes/
│ │ │ ├── certs/
│ │ │ │ ├── cloud_root_ca.crt
│ │ │ │ ├── intermediate_ca.crt
│ │ │ │ └── root_ca.crt
│ │ │ ├── config/
│ │ │ │ ├── ca.federated.json
│ │ │ │ └── ca.json
│ │ │ └── secrets/
│ │ │ ├── intermediate_ca_key
│ │ │ └── root_ca_key
│ │ └── server/
│ │ └── main.go
│ ├── bootstrap-client/
│ │ └── client.go
│ ├── bootstrap-mtls-server/
│ │ └── server.go
│ ├── bootstrap-tls-server/
│ │ └── server.go
│ ├── docker/
│ │ ├── Makefile
│ │ ├── ca/
│ │ │ ├── Dockerfile
│ │ │ └── pki/
│ │ │ ├── config/
│ │ │ │ └── ca.json
│ │ │ └── secrets/
│ │ │ ├── intermediate_ca.crt
│ │ │ ├── intermediate_ca_key
│ │ │ ├── root_ca.crt
│ │ │ └── root_ca_key
│ │ ├── docker-compose.yml
│ │ ├── nginx/
│ │ │ ├── Dockerfile
│ │ │ ├── certwatch.sh
│ │ │ ├── entrypoint.sh
│ │ │ └── site.conf
│ │ ├── password.txt
│ │ └── renewer/
│ │ ├── Dockerfile
│ │ ├── crontab
│ │ └── entrypoint.sh
│ ├── pki/
│ │ ├── config/
│ │ │ └── ca.json
│ │ └── secrets/
│ │ ├── intermediate_ca.crt
│ │ ├── intermediate_ca_key
│ │ ├── root_ca.crt
│ │ └── root_ca_key
│ └── puppet/
│ ├── ca.json.erb
│ ├── defaults.json.erb
│ ├── step.pp
│ ├── step_ca.pp
│ └── tls_server.pp
├── go.mod
├── go.sum
├── internal/
│ ├── cast/
│ │ ├── cast.go
│ │ └── cast_test.go
│ ├── httptransport/
│ │ └── httptransport.go
│ ├── metrix/
│ │ └── meter.go
│ └── userid/
│ └── userid.go
├── logging/
│ ├── clf.go
│ ├── handler.go
│ ├── handler_test.go
│ ├── logger.go
│ └── responselogger.go
├── middleware/
│ └── requestid/
│ ├── requestid.go
│ └── requestid_test.go
├── monitoring/
│ └── monitoring.go
├── pki/
│ ├── helm.go
│ ├── helm_test.go
│ ├── pki.go
│ ├── pki_test.go
│ ├── templates.go
│ └── testdata/
│ └── helm/
│ ├── simple.yml
│ ├── with-acme-and-duplicate-provisioner-name.yml
│ ├── with-acme.yml
│ ├── with-admin.yml
│ ├── with-provisioner.yml
│ ├── with-ssh-and-acme.yml
│ ├── with-ssh-and-duplicate-provisioner-name.yml
│ └── with-ssh.yml
├── policy/
│ ├── engine.go
│ ├── engine_test.go
│ ├── options.go
│ ├── options_test.go
│ ├── ssh.go
│ ├── validate.go
│ └── x509.go
├── scep/
│ ├── api/
│ │ ├── api.go
│ │ └── api_test.go
│ ├── authority.go
│ ├── authority_test.go
│ ├── options.go
│ ├── provisioner.go
│ └── scep.go
├── scripts/
│ ├── README.md
│ ├── badger-migration/
│ │ └── main.go
│ ├── install-step-ra.sh
│ ├── package-repo-import.sh
│ └── package-upload.sh
├── server/
│ └── server.go
├── systemd/
│ ├── README.md
│ └── step-ca.service
├── templates/
│ ├── templates.go
│ ├── templates_test.go
│ ├── values.go
│ └── values_test.go
├── test/
│ └── integration/
│ ├── requestid_test.go
│ └── scep/
│ ├── common_test.go
│ ├── decrypter_cas_test.go
│ ├── decrypter_test.go
│ ├── internal/
│ │ └── x509/
│ │ ├── debug.go
│ │ ├── doc.go
│ │ ├── oid.go
│ │ ├── parser.go
│ │ ├── pkcs1.go
│ │ ├── verify.go
│ │ └── x509.go
│ ├── regular_cas_test.go
│ ├── regular_test.go
│ ├── windows_go1.23_test.go
│ └── windows_test.go
├── tools.go
└── webhook/
├── options.go
├── options_test.go
└── types.go
Showing preview only (391K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4161 symbols across 333 files)
FILE: acme/account.go
type Account (line 16) | type Account struct
method GetLocation (line 29) | func (a *Account) GetLocation() string {
method ToLog (line 37) | func (a *Account) ToLog() (interface{}, error) {
method IsValid (line 46) | func (a *Account) IsValid() bool {
function KeyToID (line 51) | func KeyToID(jwk *jose.JSONWebKey) (string, error) {
type PolicyNames (line 60) | type PolicyNames struct
type X509Policy (line 66) | type X509Policy struct
type Policy (line 73) | type Policy struct
method GetAllowedNameOptions (line 77) | func (p *Policy) GetAllowedNameOptions() *policy.X509NameOptions {
method GetDeniedNameOptions (line 87) | func (p *Policy) GetDeniedNameOptions() *policy.X509NameOptions {
method AreWildcardNamesAllowed (line 100) | func (p *Policy) AreWildcardNamesAllowed() bool {
type ExternalAccountKey (line 108) | type ExternalAccountKey struct
method AlreadyBound (line 121) | func (eak *ExternalAccountKey) AlreadyBound() bool {
method BindTo (line 127) | func (eak *ExternalAccountKey) BindTo(account *Account) error {
FILE: acme/account_test.go
function TestKeyToID (line 15) | func TestKeyToID(t *testing.T) {
function TestAccount_GetLocation (line 69) | func TestAccount_GetLocation(t *testing.T) {
function TestAccount_IsValid (line 86) | func TestAccount_IsValid(t *testing.T) {
function TestExternalAccountKey_BindTo (line 102) | func TestExternalAccountKey_BindTo(t *testing.T) {
FILE: acme/api/account.go
type NewAccountRequest (line 17) | type NewAccountRequest struct
method Validate (line 34) | func (n *NewAccountRequest) Validate() error {
function validateContacts (line 24) | func validateContacts(cs []string) error {
type UpdateAccountRequest (line 42) | type UpdateAccountRequest struct
method Validate (line 48) | func (u *UpdateAccountRequest) Validate() error {
function getAccountLocationPath (line 73) | func getAccountLocationPath(ctx context.Context, linker acme.Linker, acc...
function NewAccount (line 78) | func NewAccount(w http.ResponseWriter, r *http.Request) {
function GetOrUpdateAccount (line 170) | func GetOrUpdateAccount(w http.ResponseWriter, r *http.Request) {
function logOrdersByAccount (line 219) | func logOrdersByAccount(w http.ResponseWriter, oids []string) {
function GetOrdersByAccountID (line 229) | func GetOrdersByAccountID(w http.ResponseWriter, r *http.Request) {
FILE: acme/api/account_test.go
type fakeProvisioner (line 39) | type fakeProvisioner struct
method AuthorizeOrderIdentifier (line 41) | func (*fakeProvisioner) AuthorizeOrderIdentifier(context.Context, prov...
method AuthorizeSign (line 44) | func (*fakeProvisioner) AuthorizeSign(context.Context, string) ([]prov...
method IsChallengeEnabled (line 47) | func (*fakeProvisioner) IsChallengeEnabled(context.Context, provisione...
method IsAttestationFormatEnabled (line 50) | func (*fakeProvisioner) IsAttestationFormatEnabled(context.Context, pr...
method GetAttestationRoots (line 53) | func (*fakeProvisioner) GetAttestationRoots() (*x509.CertPool, bool) ...
method AuthorizeRevoke (line 54) | func (*fakeProvisioner) AuthorizeRevoke(context.Context, string) error...
method GetID (line 55) | func (*fakeProvisioner) GetID() string ...
method GetName (line 56) | func (*fakeProvisioner) GetName() string ...
method DefaultTLSCertDuration (line 57) | func (*fakeProvisioner) DefaultTLSCertDuration() time.Duration ...
method GetOptions (line 58) | func (*fakeProvisioner) GetOptions() *provisioner.Options ...
function newProv (line 60) | func newProv() acme.Provisioner {
function newProvWithID (line 72) | func newProvWithID() acme.Provisioner {
function newProvWithOptions (line 85) | func newProvWithOptions(options *provisioner.Options) acme.Provisioner {
function newACMEProv (line 98) | func newACMEProv(t *testing.T) *provisioner.ACME {
function newACMEProvWithOptions (line 107) | func newACMEProvWithOptions(t *testing.T, options *provisioner.Options) ...
function createEABJWS (line 116) | func createEABJWS(jwk *jose.JSONWebKey, hmacKey []byte, keyID, u string)...
function createRawEABJWS (line 157) | func createRawEABJWS(jwk *jose.JSONWebKey, hmacKey []byte, keyID, u stri...
function TestNewAccountRequest_Validate (line 167) | func TestNewAccountRequest_Validate(t *testing.T) {
function TestUpdateAccountRequest_Validate (line 224) | func TestUpdateAccountRequest_Validate(t *testing.T) {
function TestHandler_GetOrdersByAccountID (line 296) | func TestHandler_GetOrdersByAccountID(t *testing.T) {
function TestHandler_NewAccount (line 413) | func TestHandler_NewAccount(t *testing.T) {
function TestHandler_GetOrUpdateAccount (line 855) | func TestHandler_GetOrUpdateAccount(t *testing.T) {
FILE: acme/api/eab.go
type ExternalAccountBinding (line 14) | type ExternalAccountBinding struct
function validateExternalAccountBinding (line 21) | func validateExternalAccountBinding(ctx context.Context, nar *NewAccount...
function keysAreEqual (line 99) | func keysAreEqual(x, y *jose.JSONWebKey) bool {
function validateEABJWS (line 118) | func validateEABJWS(ctx context.Context, jws *jose.JSONWebSignature) (st...
FILE: acme/api/eab_test.go
function Test_keysAreEqual (line 19) | func Test_keysAreEqual(t *testing.T) {
function TestHandler_validateExternalAccountBinding (line 78) | func TestHandler_validateExternalAccountBinding(t *testing.T) {
function Test_validateEABJWS (line 889) | func Test_validateEABJWS(t *testing.T) {
FILE: acme/api/handler.go
function link (line 21) | func link(url, typ string) string {
type Clock (line 26) | type Clock struct
method Now (line 29) | func (c *Clock) Now() time.Time {
type payloadInfo (line 35) | type payloadInfo struct
type HandlerOptions (line 42) | type HandlerOptions struct
type handler (line 78) | type handler struct
method Route (line 89) | func (h *handler) Route(r api.Router) {
function NewHandler (line 109) | func NewHandler(opts HandlerOptions) api.RouterHandler {
function Route (line 118) | func Route(r api.Router) {
function route (line 122) | func route(r api.Router, middleware func(next nextHTTP) nextHTTP) {
function GetNonce (line 186) | func GetNonce(w http.ResponseWriter, r *http.Request) {
type Meta (line 194) | type Meta struct
type Directory (line 202) | type Directory struct
method ToLog (line 212) | func (d *Directory) ToLog() (interface{}, error) {
function GetDirectory (line 222) | func GetDirectory(w http.ResponseWriter, r *http.Request) {
function createMetaObject (line 245) | func createMetaObject(p *provisioner.ACME) *Meta {
function shouldAddMetaObject (line 259) | func shouldAddMetaObject(p *provisioner.ACME) bool {
function NotImplemented (line 276) | func NotImplemented(w http.ResponseWriter, r *http.Request) {
function GetAuthorization (line 281) | func GetAuthorization(w http.ResponseWriter, r *http.Request) {
function GetChallenge (line 313) | func GetChallenge(w http.ResponseWriter, r *http.Request) {
function GetCertificate (line 366) | func GetCertificate(w http.ResponseWriter, r *http.Request) {
FILE: acme/api/handler_test.go
type mockClient (line 30) | type mockClient struct
method Get (line 36) | func (m *mockClient) Get(u string) (*http.Response, error) { return...
method LookupTxt (line 37) | func (m *mockClient) LookupTxt(name string) ([]string, error) { return...
method TLSDial (line 38) | func (m *mockClient) TLSDial(network, addr string, config *tls.Config)...
function mockMustAuthority (line 42) | func mockMustAuthority(t *testing.T, a acme.CertificateAuthority) {
function TestHandler_GetNonce (line 53) | func TestHandler_GetNonce(t *testing.T) {
function TestHandler_GetDirectory (line 80) | func TestHandler_GetDirectory(t *testing.T) {
function TestHandler_GetAuthorization (line 210) | func TestHandler_GetAuthorization(t *testing.T) {
function TestHandler_GetCertificate (line 383) | func TestHandler_GetCertificate(t *testing.T) {
function TestHandler_GetChallenge (line 520) | func TestHandler_GetChallenge(t *testing.T) {
function Test_createMetaObject (line 782) | func Test_createMetaObject(t *testing.T) {
FILE: acme/api/middleware.go
function logNonce (line 24) | func logNonce(w http.ResponseWriter, nonce string) {
function addNonce (line 34) | func addNonce(next nextHTTP) nextHTTP {
function addDirLink (line 51) | func addDirLink(next nextHTTP) nextHTTP {
function verifyContentType (line 63) | func verifyContentType(next nextHTTP) nextHTTP {
function parseJWS (line 97) | func parseJWS(next nextHTTP) nextHTTP {
function validateJWS (line 129) | func validateJWS(next nextHTTP) nextHTTP {
function extractJWK (line 217) | func extractJWK(next nextHTTP) nextHTTP {
function checkPrerequisites (line 269) | func checkPrerequisites(next nextHTTP) nextHTTP {
function lookupJWK (line 292) | func lookupJWK(next nextHTTP) nextHTTP {
function extractOrLookupJWK (line 374) | func extractOrLookupJWK(next nextHTTP) nextHTTP {
function canExtractJWKFrom (line 398) | func canExtractJWKFrom(jws *jose.JSONWebSignature) bool {
function verifyAndExtractJWSPayload (line 410) | func verifyAndExtractJWSPayload(next nextHTTP) nextHTTP {
function retryVerificationWithPatchedSignatures (line 459) | func retryVerificationWithPatchedSignatures(jws *jose.JSONWebSignature, ...
function isPostAsGet (line 550) | func isPostAsGet(next nextHTTP) nextHTTP {
type ContextKey (line 567) | type ContextKey
constant accContextKey (line 571) | accContextKey = ContextKey("acc")
constant jwsContextKey (line 573) | jwsContextKey = ContextKey("jws")
constant jwkContextKey (line 575) | jwkContextKey = ContextKey("jwk")
constant payloadContextKey (line 577) | payloadContextKey = ContextKey("payload")
function accountFromContext (line 582) | func accountFromContext(ctx context.Context) (*acme.Account, error) {
function jwkFromContext (line 591) | func jwkFromContext(ctx context.Context) (*jose.JSONWebKey, error) {
function jwsFromContext (line 600) | func jwsFromContext(ctx context.Context) (*jose.JSONWebSignature, error) {
function provisionerFromContext (line 610) | func provisionerFromContext(ctx context.Context) (acme.Provisioner, erro...
function acmeProvisionerFromContext (line 620) | func acmeProvisionerFromContext(ctx context.Context) (*provisioner.ACME,...
function payloadFromContext (line 635) | func payloadFromContext(ctx context.Context) (*payloadInfo, error) {
FILE: acme/api/middleware_test.go
function testNext (line 29) | func testNext(w http.ResponseWriter, _ *http.Request) {
function newBaseContext (line 33) | func newBaseContext(ctx context.Context, args ...interface{}) context.Co...
function TestHandler_addNonce (line 47) | func TestHandler_addNonce(t *testing.T) {
function TestHandler_addDirLink (line 109) | func TestHandler_addDirLink(t *testing.T) {
function TestHandler_verifyContentType (line 161) | func TestHandler_verifyContentType(t *testing.T) {
function TestHandler_isPostAsGet (line 264) | func TestHandler_isPostAsGet(t *testing.T) {
type errReader (line 331) | type errReader
method Read (line 333) | func (errReader) Read([]byte) (int, error) {
method Close (line 336) | func (errReader) Close() error {
function TestHandler_parseJWS (line 340) | func TestHandler_parseJWS(t *testing.T) {
function TestHandler_verifyAndExtractJWSPayload (line 420) | func TestHandler_verifyAndExtractJWSPayload(t *testing.T) {
function TestHandler_lookupJWK (line 674) | func TestHandler_lookupJWK(t *testing.T) {
function TestHandler_extractJWK (line 976) | func TestHandler_extractJWK(t *testing.T) {
function TestHandler_validateJWS (line 1175) | func TestHandler_validateJWS(t *testing.T) {
function Test_canExtractJWKFrom (line 1550) | func Test_canExtractJWKFrom(t *testing.T) {
function TestHandler_extractOrLookupJWK (line 1615) | func TestHandler_extractOrLookupJWK(t *testing.T) {
function TestHandler_checkPrerequisites (line 1732) | func TestHandler_checkPrerequisites(t *testing.T) {
function Test_retryVerificationWithPatchedSignatures (line 1816) | func Test_retryVerificationWithPatchedSignatures(t *testing.T) {
FILE: acme/api/order.go
type NewOrderRequest (line 27) | type NewOrderRequest struct
method Validate (line 34) | func (n *NewOrderRequest) Validate() error {
method validateWireIdentifiers (line 72) | func (n *NewOrderRequest) validateWireIdentifiers() error {
method hasWireIdentifiers (line 114) | func (n *NewOrderRequest) hasWireIdentifiers() bool {
function identifiersOfType (line 124) | func identifiersOfType(typ acme.IdentifierType, ids []acme.Identifier) (...
type FinalizeRequest (line 134) | type FinalizeRequest struct
method Validate (line 140) | func (f *FinalizeRequest) Validate() error {
function NewOrder (line 166) | func NewOrder(w http.ResponseWriter, r *http.Request) {
function isIdentifierAllowed (line 297) | func isIdentifierAllowed(acmePolicy policy.X509Policy, identifier acme.I...
function newACMEPolicyEngine (line 304) | func newACMEPolicyEngine(eak *acme.ExternalAccountKey) (policy.X509Polic...
function trimIfWildcard (line 312) | func trimIfWildcard(value string) (string, bool) {
function newAuthorization (line 319) | func newAuthorization(ctx context.Context, az *acme.Authorization) error {
function GetOrder (line 393) | func GetOrder(w http.ResponseWriter, r *http.Request) {
function FinalizeOrder (line 436) | func FinalizeOrder(w http.ResponseWriter, r *http.Request) {
function challengeTypes (line 497) | func challengeTypes(az *acme.Authorization) []acme.ChallengeType {
FILE: acme/api/order_test.go
function TestNewOrderRequest_Validate (line 33) | func TestNewOrderRequest_Validate(t *testing.T) {
function TestFinalizeRequestValidate (line 263) | func TestFinalizeRequestValidate(t *testing.T) {
function TestHandler_GetOrder (line 327) | func TestHandler_GetOrder(t *testing.T) {
function TestHandler_newAuthorization (line 557) | func TestHandler_newAuthorization(t *testing.T) {
function TestHandler_NewOrder (line 1058) | func TestHandler_NewOrder(t *testing.T) {
function TestHandler_FinalizeOrder (line 2375) | func TestHandler_FinalizeOrder(t *testing.T) {
function TestHandler_challengeTypes (line 2673) | func TestHandler_challengeTypes(t *testing.T) {
function TestTrimIfWildcard (line 2722) | func TestTrimIfWildcard(t *testing.T) {
FILE: acme/api/revoke.go
type revokePayload (line 23) | type revokePayload struct
function RevokeCert (line 29) | func RevokeCert(w http.ResponseWriter, r *http.Request) {
function isAccountAuthorized (line 154) | func isAccountAuthorized(_ context.Context, dbCert *acme.Certificate, ce...
function wrapRevokeErr (line 180) | func wrapRevokeErr(err error) *acme.Error {
function wrapUnauthorizedError (line 190) | func wrapUnauthorizedError(cert *x509.Certificate, unauthorizedIdentifie...
function logRevoke (line 213) | func logRevoke(w http.ResponseWriter, ri *authority.RevokeOptions) {
function validateReasonCode (line 226) | func validateReasonCode(reasonCode *int) *acme.Error {
function revokeOptions (line 240) | func revokeOptions(serial string, certToBeRevoked *x509.Certificate, rea...
function reason (line 255) | func reason(reasonCode int) string {
function shouldCheckAccountFrom (line 289) | func shouldCheckAccountFrom(jws *jose.JSONWebSignature) bool {
FILE: acme/api/revoke_test.go
function v (line 40) | func v(v int) *int {
function generateSerial (line 44) | func generateSerial() (*big.Int, error) {
function generateCertKeyPair (line 49) | func generateCertKeyPair() (*x509.Certificate, crypto.Signer, error) {
type keyID (line 87) | type keyID
constant noKeyID (line 91) | noKeyID = keyID("")
function jwsEncodeJSON (line 106) | func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid keyID, n...
function jwsHasher (line 144) | func jwsHasher(pub crypto.PublicKey) (string, crypto.Hash) {
function jwsSign (line 169) | func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte...
function jwsHead (line 196) | func jwsHead(alg, nonce, u string, kid keyID, key crypto.Signer) (string...
function jwkEncode (line 220) | func jwkEncode(pub crypto.PublicKey) (string, error) {
function jwsFinal (line 261) | func jwsFinal(_ crypto.Hash, sig []byte, phead, payload string) ([]byte,...
type mockCA (line 278) | type mockCA struct
method SignWithContext (line 285) | func (m *mockCA) SignWithContext(context.Context, *x509.CertificateReq...
method AreSANsAllowed (line 289) | func (m *mockCA) AreSANsAllowed(ctx context.Context, sans []string) er...
method IsRevoked (line 296) | func (m *mockCA) IsRevoked(sn string) (bool, error) {
method Revoke (line 303) | func (m *mockCA) Revoke(ctx context.Context, opts *authority.RevokeOpt...
method LoadProvisionerByName (line 310) | func (m *mockCA) LoadProvisionerByName(string) (provisioner.Interface,...
method GetBackdate (line 314) | func (m *mockCA) GetBackdate() *time.Duration {
function Test_validateReasonCode (line 321) | func Test_validateReasonCode(t *testing.T) {
function Test_reason (line 366) | func Test_reason(t *testing.T) {
function Test_revokeOptions (line 437) | func Test_revokeOptions(t *testing.T) {
function TestHandler_RevokeCert (line 487) | func TestHandler_RevokeCert(t *testing.T) {
function TestHandler_isAccountAuthorized (line 1111) | func TestHandler_isAccountAuthorized(t *testing.T) {
function Test_wrapUnauthorizedError (line 1245) | func Test_wrapUnauthorizedError(t *testing.T) {
FILE: acme/api/wire_integration_test.go
constant baseURL (line 41) | baseURL = "test.ca.smallstep.com"
constant linkerPrefix (line 42) | linkerPrefix = "acme"
function newWireProvisionerWithOptions (line 45) | func newWireProvisionerWithOptions(t *testing.T, options *provisioner.Op...
function TestWireIntegration (line 67) | func TestWireIntegration(t *testing.T) {
type mockCASigner (line 590) | type mockCASigner struct
method SignWithContext (line 594) | func (m *mockCASigner) SignWithContext(_ context.Context, cr *x509.Cer...
method AreSANsAllowed (line 601) | func (m *mockCASigner) AreSANsAllowed(ctx context.Context, sans []stri...
method IsRevoked (line 605) | func (m *mockCASigner) IsRevoked(sn string) (bool, error) {
method Revoke (line 609) | func (m *mockCASigner) Revoke(ctx context.Context, opts *authority.Rev...
method LoadProvisionerByName (line 613) | func (m *mockCASigner) LoadProvisionerByName(string) (provisioner.Inte...
method GetBackdate (line 617) | func (m *mockCASigner) GetBackdate() *time.Duration {
FILE: acme/authorization.go
type Authorization (line 10) | type Authorization struct
method ToLog (line 24) | func (az *Authorization) ToLog() (interface{}, error) {
method UpdateStatus (line 34) | func (az *Authorization) UpdateStatus(ctx context.Context, db DB) error {
FILE: acme/authorization_test.go
function TestAuthorization_UpdateStatus (line 12) | func TestAuthorization_UpdateStatus(t *testing.T) {
FILE: acme/certificate.go
type Certificate (line 8) | type Certificate struct
FILE: acme/challenge.go
type ChallengeType (line 46) | type ChallengeType
constant HTTP01 (line 50) | HTTP01 ChallengeType = "http-01"
constant DNS01 (line 52) | DNS01 ChallengeType = "dns-01"
constant TLSALPN01 (line 54) | TLSALPN01 ChallengeType = "tls-alpn-01"
constant DEVICEATTEST01 (line 56) | DEVICEATTEST01 ChallengeType = "device-attest-01"
constant WIREOIDC01 (line 58) | WIREOIDC01 ChallengeType = "wire-oidc-01"
constant WIREDPOP01 (line 60) | WIREDPOP01 ChallengeType = "wire-dpop-01"
type Challenge (line 81) | type Challenge struct
method ToLog (line 98) | func (ch *Challenge) ToLog() (interface{}, error) {
method Validate (line 109) | func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JS...
function http01Validate (line 140) | func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose...
function rootedName (line 192) | func rootedName(name string) string {
function http01ChallengeHost (line 205) | func http01ChallengeHost(value string) string {
function tlsAlpn01ChallengeHost (line 217) | func tlsAlpn01ChallengeHost(name string) string {
function dns01ChallengeHost (line 225) | func dns01ChallengeHost(domain string) string {
function tlsAlert (line 229) | func tlsAlert(err error) uint8 {
function tlsalpn01Validate (line 240) | func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *j...
function dns01Validate (line 359) | func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose....
type wireOidcPayload (line 402) | type wireOidcPayload struct
function wireOIDC01Validate (line 407) | func wireOIDC01Validate(ctx context.Context, ch *Challenge, db WireDB, j...
function validateWireOIDCClaims (line 503) | func validateWireOIDCClaims(o *wireprovisioner.OIDCOptions, token *oidc....
type wireDpopPayload (line 532) | type wireDpopPayload struct
function wireDPOP01Validate (line 537) | func wireDPOP01Validate(ctx context.Context, ch *Challenge, db WireDB, a...
type wireCnf (line 617) | type wireCnf struct
type wireAccessToken (line 621) | type wireAccessToken struct
type wireDpopJwt (line 632) | type wireDpopJwt struct
type wireDpopToken (line 640) | type wireDpopToken
type wireVerifyParams (line 642) | type wireVerifyParams struct
function parseAndVerifyWireAccessToken (line 654) | func parseAndVerifyWireAccessToken(v wireVerifyParams) (*wireAccessToken...
type payloadType (line 783) | type payloadType struct
type attestationObject (line 788) | type attestationObject struct
function deviceAttest01Validate (line 794) | func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, j...
type tpmAttestationData (line 973) | type tpmAttestationData struct
type coseAlgorithmIdentifier (line 982) | type coseAlgorithmIdentifier
constant coseAlgES256 (line 985) | coseAlgES256 = coseAlgorithmIdentifier(-7)
constant coseAlgRS256 (line 986) | coseAlgRS256 = coseAlgorithmIdentifier(-257)
constant coseAlgRS1 (line 987) | coseAlgRS1 = coseAlgorithmIdentifier(-65535)
function doTPMAttestationFormat (line 990) | func doTPMAttestationFormat(_ context.Context, prov Provisioner, ch *Cha...
function validateAKCertificate (line 1205) | func validateAKCertificate(c *x509.Certificate) error {
function validateAKCertificateSubjectAlternativeNames (line 1223) | func validateAKCertificateSubjectAlternativeNames(c *x509.Certificate) e...
function validateAKCertificateExtendedKeyUsage (line 1246) | func validateAKCertificateExtendedKeyUsage(c *x509.Certificate) error {
constant appleEnterpriseAttestationRootCA (line 1269) | appleEnterpriseAttestationRootCA = `-----BEGIN CERTIFICATE-----
type appleAttestationData (line 1291) | type appleAttestationData struct
function doAppleAttestationFormat (line 1300) | func doAppleAttestationFormat(_ context.Context, prov Provisioner, _ *Ch...
constant yubicoPIVRootCA (line 1375) | yubicoPIVRootCA = `-----BEGIN CERTIFICATE-----
constant yubicoAttestationRootCA (line 1397) | yubicoAttestationRootCA = `-----BEGIN CERTIFICATE-----
type stepAttestationData (line 1427) | type stepAttestationData struct
function doStepAttestationFormat (line 1433) | func doStepAttestationFormat(_ context.Context, prov Provisioner, ch *Ch...
function searchSerialNumber (line 1546) | func searchSerialNumber(cert *x509.Certificate) (string, error) {
function serverName (line 1576) | func serverName(ch *Challenge) string {
function reverseAddr (line 1587) | func reverseAddr(ip net.IP) (arpa string) {
function uitoa (line 1608) | func uitoa(val uint) string {
constant hexit (line 1625) | hexit = "0123456789abcdef"
function KeyAuthorization (line 1629) | func KeyAuthorization(token string, jwk *jose.JSONWebKey) (string, error) {
function storeError (line 1639) | func storeError(ctx context.Context, db DB, ch *Challenge, markInvalid b...
FILE: acme/challenge_test.go
type mockClient (line 48) | type mockClient struct
method Get (line 54) | func (m *mockClient) Get(url string) (*http.Response, error) { return...
method LookupTxt (line 55) | func (m *mockClient) LookupTxt(name string) ([]string, error) { return...
method TLSDial (line 56) | func (m *mockClient) TLSDial(network, addr string, tlsConfig *tls.Conf...
function fatalError (line 60) | func fatalError(t *testing.T, err error) {
function mustNonAttestationProvisioner (line 67) | func mustNonAttestationProvisioner(t *testing.T) Provisioner {
function mustAttestationProvisioner (line 84) | func mustAttestationProvisioner(t *testing.T, roots []byte) Provisioner {
function mustAccountAndKeyAuthorization (line 101) | func mustAccountAndKeyAuthorization(t *testing.T, token string) (*jose.J...
function mustAttestApple (line 112) | func mustAttestApple(t *testing.T, nonce string) ([]byte, *x509.Certific...
function mustAttestYubikey (line 155) | func mustAttestYubikey(t *testing.T, _, keyAuthorization string, serial ...
type stepManagedDevice (line 205) | type stepManagedDevice struct
function mustAttestStepManagedDeviceID (line 209) | func mustAttestStepManagedDeviceID(t *testing.T, _, keyAuthorization, se...
function newWireProvisionerWithOptions (line 259) | func newWireProvisionerWithOptions(t *testing.T, options *provisioner.Op...
function Test_storeError (line 278) | func Test_storeError(t *testing.T) {
function TestKeyAuthorization (line 421) | func TestKeyAuthorization(t *testing.T) {
function TestChallenge_Validate (line 477) | func TestChallenge_Validate(t *testing.T) {
function mustJWKServer (line 1465) | func mustJWKServer(t *testing.T, pub jose.JSONWebKey) *httptest.Server {
type errReader (line 1503) | type errReader
method Read (line 1505) | func (errReader) Read([]byte) (int, error) {
method Close (line 1508) | func (errReader) Close() error {
function TestHTTP01Validate (line 1512) | func TestHTTP01Validate(t *testing.T) {
function TestDNS01Validate (line 1904) | func TestDNS01Validate(t *testing.T) {
type tlsDialer (line 2205) | type tlsDialer
function newTestTLSALPNServer (line 2207) | func newTestTLSALPNServer(validationCert *tls.Certificate, opts ...func(...
type noopConn (line 2246) | type noopConn struct
method Read (line 2248) | func (c *noopConn) Read(_ []byte) (n int, err error) { return 0, io.E...
method Write (line 2249) | func (c *noopConn) Write(_ []byte) (n int, err error) { return 0, io.E...
method Close (line 2250) | func (c *noopConn) Close() error { return nil }
method LocalAddr (line 2251) | func (c *noopConn) LocalAddr() net.Addr { return &net.IP...
method RemoteAddr (line 2252) | func (c *noopConn) RemoteAddr() net.Addr { return &net.IP...
method SetDeadline (line 2253) | func (c *noopConn) SetDeadline(time.Time) error { return nil }
method SetReadDeadline (line 2254) | func (c *noopConn) SetReadDeadline(time.Time) error { return nil }
method SetWriteDeadline (line 2255) | func (c *noopConn) SetWriteDeadline(time.Time) error { return nil }
function newTLSALPNValidationCert (line 2257) | func newTLSALPNValidationCert(keyAuthHash []byte, obsoleteOID, critical ...
function TestTLSALPN01Validate (line 2304) | func TestTLSALPN01Validate(t *testing.T) {
function Test_reverseAddr (line 3303) | func Test_reverseAddr(t *testing.T) {
function Test_serverName (line 3336) | func Test_serverName(t *testing.T) {
function Test_http01ChallengeHost (line 3382) | func Test_http01ChallengeHost(t *testing.T) {
function Test_doAppleAttestationFormat (line 3438) | func Test_doAppleAttestationFormat(t *testing.T) {
function Test_doStepAttestationFormat (line 3555) | func Test_doStepAttestationFormat(t *testing.T) {
function Test_doStepAttestationFormat_noCAIntermediate (line 3808) | func Test_doStepAttestationFormat_noCAIntermediate(t *testing.T) {
function Test_deviceAttest01Validate (line 3902) | func Test_deviceAttest01Validate(t *testing.T) {
function generateValidAKCertificate (line 4939) | func generateValidAKCertificate(t *testing.T) *x509.Certificate {
function Test_validateAKCertificate (line 4965) | func Test_validateAKCertificate(t *testing.T) {
function Test_validateAKCertificateSubjectAlternativeNames (line 5023) | func Test_validateAKCertificateSubjectAlternativeNames(t *testing.T) {
function Test_validateAKCertificateExtendedKeyUsage (line 5104) | func Test_validateAKCertificateExtendedKeyUsage(t *testing.T) {
function createSubjectAltNameExtension (line 5161) | func createSubjectAltNameExtension(dnsNames, emailAddresses x509util.Mul...
function Test_tlsAlpn01ChallengeHost (line 5231) | func Test_tlsAlpn01ChallengeHost(t *testing.T) {
function Test_dns01ChallengeHost (line 5260) | func Test_dns01ChallengeHost(t *testing.T) {
FILE: acme/challenge_tpmsimulator_test.go
function newSimulatedTPM (line 33) | func newSimulatedTPM(t *testing.T) *tpm.TPM {
function withSimulator (line 41) | func withSimulator(t *testing.T) tpm.NewTPMOption {
function generateKeyID (line 58) | func generateKeyID(t *testing.T, pub crypto.PublicKey) []byte {
function mustAttestTPM (line 66) | func mustAttestTPM(t *testing.T, keyAuthorization string, permanentIdent...
function Test_deviceAttest01ValidateWithTPMSimulator (line 171) | func Test_deviceAttest01ValidateWithTPMSimulator(t *testing.T) {
function newBadAttestationStatementError (line 406) | func newBadAttestationStatementError(msg string) *Error {
function newInternalServerError (line 414) | func newInternalServerError(msg string) *Error {
function Test_doTPMAttestationFormat (line 427) | func Test_doTPMAttestationFormat(t *testing.T) {
FILE: acme/challenge_wire_test.go
function Test_wireDPOP01Validate (line 25) | func Test_wireDPOP01Validate(t *testing.T) {
function Test_wireOIDC01Validate (line 1078) | func Test_wireOIDC01Validate(t *testing.T) {
function Test_parseAndVerifyWireAccessToken (line 2125) | func Test_parseAndVerifyWireAccessToken(t *testing.T) {
function Test_validateWireOIDCClaims (line 2197) | func Test_validateWireOIDCClaims(t *testing.T) {
function createWireOptions (line 2247) | func createWireOptions(t *testing.T, transformTemplate string) *wireprov...
function Test_idTokenTransformation (line 2277) | func Test_idTokenTransformation(t *testing.T) {
FILE: acme/client.go
type Client (line 12) | type Client interface
type clientKey (line 24) | type clientKey struct
function NewClientContext (line 27) | func NewClientContext(ctx context.Context, c Client) context.Context {
function ClientFromContext (line 32) | func ClientFromContext(ctx context.Context) (c Client, ok bool) {
function MustClientFromContext (line 39) | func MustClientFromContext(ctx context.Context) Client {
type client (line 47) | type client struct
method Get (line 71) | func (c *client) Get(url string) (*http.Response, error) {
method LookupTxt (line 75) | func (c *client) LookupTxt(name string) ([]string, error) {
method TLSDial (line 79) | func (c *client) TLSDial(network, addr string, config *tls.Config) (*t...
function NewClient (line 53) | func NewClient() Client {
FILE: acme/common.go
type Clock (line 13) | type Clock struct
method Now (line 16) | func (c *Clock) Now() time.Time {
type CertificateAuthority (line 23) | type CertificateAuthority interface
function NewContext (line 33) | func NewContext(ctx context.Context, db DB, client Client, linker Linker...
type PrerequisitesChecker (line 46) | type PrerequisitesChecker
function DefaultPrerequisitesChecker (line 50) | func DefaultPrerequisitesChecker(context.Context) (bool, error) {
type prerequisitesKey (line 54) | type prerequisitesKey struct
function NewPrerequisitesCheckerContext (line 58) | func NewPrerequisitesCheckerContext(ctx context.Context, fn Prerequisite...
function PrerequisitesCheckerFromContext (line 64) | func PrerequisitesCheckerFromContext(ctx context.Context) (Prerequisites...
type Provisioner (line 71) | type Provisioner interface
type provisionerKey (line 84) | type provisionerKey struct
function NewProvisionerContext (line 87) | func NewProvisionerContext(ctx context.Context, v Provisioner) context.C...
function ProvisionerFromContext (line 92) | func ProvisionerFromContext(ctx context.Context) (v Provisioner, ok bool) {
function MustProvisionerFromContext (line 99) | func MustProvisionerFromContext(ctx context.Context) Provisioner {
type MockProvisioner (line 111) | type MockProvisioner struct
method GetName (line 127) | func (m *MockProvisioner) GetName() string {
method AuthorizeOrderIdentifier (line 135) | func (m *MockProvisioner) AuthorizeOrderIdentifier(ctx context.Context...
method AuthorizeSign (line 143) | func (m *MockProvisioner) AuthorizeSign(ctx context.Context, ott strin...
method AuthorizeRevoke (line 151) | func (m *MockProvisioner) AuthorizeRevoke(ctx context.Context, token s...
method IsChallengeEnabled (line 159) | func (m *MockProvisioner) IsChallengeEnabled(ctx context.Context, chal...
method IsAttestationFormatEnabled (line 167) | func (m *MockProvisioner) IsAttestationFormatEnabled(ctx context.Conte...
method GetAttestationRoots (line 174) | func (m *MockProvisioner) GetAttestationRoots() (*x509.CertPool, bool) {
method DefaultTLSCertDuration (line 182) | func (m *MockProvisioner) DefaultTLSCertDuration() time.Duration {
method GetOptions (line 190) | func (m *MockProvisioner) GetOptions() *provisioner.Options {
method GetID (line 198) | func (m *MockProvisioner) GetID() string {
FILE: acme/db.go
function IsErrNotFound (line 18) | func IsErrNotFound(err error) bool {
type DB (line 23) | type DB interface
type WireDB (line 63) | type WireDB interface
type dbKey (line 72) | type dbKey struct
function NewDatabaseContext (line 75) | func NewDatabaseContext(ctx context.Context, db DB) context.Context {
function DatabaseFromContext (line 80) | func DatabaseFromContext(ctx context.Context) (db DB, ok bool) {
function MustDatabaseFromContext (line 87) | func MustDatabaseFromContext(ctx context.Context) DB {
type MockDB (line 100) | type MockDB struct
method CreateAccount (line 152) | func (m *MockDB) CreateAccount(ctx context.Context, acc *Account) error {
method GetAccount (line 162) | func (m *MockDB) GetAccount(ctx context.Context, id string) (*Account,...
method GetAccountByKeyID (line 172) | func (m *MockDB) GetAccountByKeyID(ctx context.Context, kid string) (*...
method UpdateAccount (line 182) | func (m *MockDB) UpdateAccount(ctx context.Context, acc *Account) error {
method CreateExternalAccountKey (line 192) | func (m *MockDB) CreateExternalAccountKey(ctx context.Context, provisi...
method GetExternalAccountKey (line 202) | func (m *MockDB) GetExternalAccountKey(ctx context.Context, provisione...
method GetExternalAccountKeys (line 212) | func (m *MockDB) GetExternalAccountKeys(ctx context.Context, provision...
method GetExternalAccountKeyByReference (line 222) | func (m *MockDB) GetExternalAccountKeyByReference(ctx context.Context,...
method GetExternalAccountKeyByAccountID (line 232) | func (m *MockDB) GetExternalAccountKeyByAccountID(ctx context.Context,...
method DeleteExternalAccountKey (line 242) | func (m *MockDB) DeleteExternalAccountKey(ctx context.Context, provisi...
method UpdateExternalAccountKey (line 252) | func (m *MockDB) UpdateExternalAccountKey(ctx context.Context, provisi...
method CreateNonce (line 262) | func (m *MockDB) CreateNonce(ctx context.Context) (Nonce, error) {
method DeleteNonce (line 272) | func (m *MockDB) DeleteNonce(ctx context.Context, nonce Nonce) error {
method CreateAuthorization (line 282) | func (m *MockDB) CreateAuthorization(ctx context.Context, az *Authoriz...
method GetAuthorization (line 292) | func (m *MockDB) GetAuthorization(ctx context.Context, id string) (*Au...
method UpdateAuthorization (line 302) | func (m *MockDB) UpdateAuthorization(ctx context.Context, az *Authoriz...
method GetAuthorizationsByAccountID (line 312) | func (m *MockDB) GetAuthorizationsByAccountID(ctx context.Context, acc...
method CreateCertificate (line 322) | func (m *MockDB) CreateCertificate(ctx context.Context, cert *Certific...
method GetCertificate (line 332) | func (m *MockDB) GetCertificate(ctx context.Context, id string) (*Cert...
method GetCertificateBySerial (line 342) | func (m *MockDB) GetCertificateBySerial(ctx context.Context, serial st...
method CreateChallenge (line 352) | func (m *MockDB) CreateChallenge(ctx context.Context, ch *Challenge) e...
method GetChallenge (line 362) | func (m *MockDB) GetChallenge(ctx context.Context, chID, azID string) ...
method UpdateChallenge (line 372) | func (m *MockDB) UpdateChallenge(ctx context.Context, ch *Challenge) e...
method CreateOrder (line 382) | func (m *MockDB) CreateOrder(ctx context.Context, o *Order) error {
method GetOrder (line 392) | func (m *MockDB) GetOrder(ctx context.Context, id string) (*Order, err...
method UpdateOrder (line 402) | func (m *MockDB) UpdateOrder(ctx context.Context, o *Order) error {
method GetOrdersByAccountID (line 412) | func (m *MockDB) GetOrdersByAccountID(ctx context.Context, accID strin...
type MockWireDB (line 142) | type MockWireDB struct
method GetAllOrdersByAccountID (line 422) | func (m *MockWireDB) GetAllOrdersByAccountID(ctx context.Context, acco...
method GetDpopToken (line 432) | func (m *MockWireDB) GetDpopToken(ctx context.Context, orderID string)...
method CreateDpopToken (line 442) | func (m *MockWireDB) CreateDpopToken(ctx context.Context, orderID stri...
method GetOidcToken (line 450) | func (m *MockWireDB) GetOidcToken(ctx context.Context, orderID string)...
method CreateOidcToken (line 460) | func (m *MockWireDB) CreateOidcToken(ctx context.Context, orderID stri...
FILE: acme/db/nosql/account.go
type dbAccount (line 15) | type dbAccount struct
method clone (line 27) | func (dba *dbAccount) clone() *dbAccount {
method getAccountIDByKeyID (line 32) | func (db *DB) getAccountIDByKeyID(_ context.Context, kid string) (string...
method getDBAccount (line 44) | func (db *DB) getDBAccount(_ context.Context, id string) (*dbAccount, er...
method GetAccount (line 61) | func (db *DB) GetAccount(ctx context.Context, id string) (*acme.Account,...
method GetAccountByKeyID (line 79) | func (db *DB) GetAccountByKeyID(ctx context.Context, kid string) (*acme....
method CreateAccount (line 88) | func (db *DB) CreateAccount(ctx context.Context, acc *acme.Account) error {
method UpdateAccount (line 129) | func (db *DB) UpdateAccount(ctx context.Context, acc *acme.Account) error {
FILE: acme/db/nosql/account_test.go
function TestDB_getDBAccount (line 18) | func TestDB_getDBAccount(t *testing.T) {
function TestDB_getAccountIDByKeyID (line 126) | func TestDB_getAccountIDByKeyID(t *testing.T) {
function TestDB_GetAccount (line 200) | func TestDB_GetAccount(t *testing.T) {
function TestDB_GetAccountByKeyID (line 283) | func TestDB_GetAccountByKeyID(t *testing.T) {
function TestDB_CreateAccount (line 389) | func TestDB_CreateAccount(t *testing.T) {
function TestDB_UpdateAccount (line 553) | func TestDB_UpdateAccount(t *testing.T) {
FILE: acme/db/nosql/authz.go
type dbAuthz (line 14) | type dbAuthz struct
method clone (line 28) | func (ba *dbAuthz) clone() *dbAuthz {
method getDBAuthz (line 35) | func (db *DB) getDBAuthz(_ context.Context, id string) (*dbAuthz, error) {
method GetAuthorization (line 52) | func (db *DB) GetAuthorization(ctx context.Context, id string) (*acme.Au...
method CreateAuthorization (line 80) | func (db *DB) CreateAuthorization(ctx context.Context, az *acme.Authoriz...
method UpdateAuthorization (line 110) | func (db *DB) UpdateAuthorization(ctx context.Context, az *acme.Authoriz...
method GetAuthorizationsByAccountID (line 124) | func (db *DB) GetAuthorizationsByAccountID(_ context.Context, accountID ...
FILE: acme/db/nosql/authz_test.go
function TestDB_getDBAuthz (line 19) | func TestDB_getDBAuthz(t *testing.T) {
function TestDB_GetAuthorization (line 133) | func TestDB_GetAuthorization(t *testing.T) {
function TestDB_CreateAuthorization (line 330) | func TestDB_CreateAuthorization(t *testing.T) {
function TestDB_UpdateAuthorization (line 460) | func TestDB_UpdateAuthorization(t *testing.T) {
function TestDB_GetAuthorizationsByAccountID (line 623) | func TestDB_GetAuthorizationsByAccountID(t *testing.T) {
FILE: acme/db/nosql/certificate.go
type dbCert (line 15) | type dbCert struct
type dbSerial (line 24) | type dbSerial struct
method CreateCertificate (line 30) | func (db *DB) CreateCertificate(ctx context.Context, cert *acme.Certific...
method GetCertificate (line 72) | func (db *DB) GetCertificate(_ context.Context, id string) (*acme.Certif...
method GetCertificateBySerial (line 100) | func (db *DB) GetCertificateBySerial(ctx context.Context, serial string)...
function parseBundle (line 116) | func parseBundle(b []byte) ([]*x509.Certificate, error) {
FILE: acme/db/nosql/certificate_test.go
function TestDB_CreateCertificate (line 22) | func TestDB_CreateCertificate(t *testing.T) {
function TestDB_GetCertificate (line 134) | func TestDB_GetCertificate(t *testing.T) {
function Test_parseBundle (line 278) | func Test_parseBundle(t *testing.T) {
function TestDB_GetCertificateBySerial (line 340) | func TestDB_GetCertificateBySerial(t *testing.T) {
FILE: acme/db/nosql/challenge.go
type dbChallenge (line 15) | type dbChallenge struct
method clone (line 28) | func (dbc *dbChallenge) clone() *dbChallenge {
method getDBChallenge (line 33) | func (db *DB) getDBChallenge(_ context.Context, id string) (*dbChallenge...
method CreateChallenge (line 50) | func (db *DB) CreateChallenge(ctx context.Context, ch *acme.Challenge) e...
method GetChallenge (line 73) | func (db *DB) GetChallenge(ctx context.Context, id, authzID string) (*ac...
method UpdateChallenge (line 95) | func (db *DB) UpdateChallenge(ctx context.Context, ch *acme.Challenge) e...
FILE: acme/db/nosql/challenge_test.go
function TestDB_getDBChallenge (line 17) | func TestDB_getDBChallenge(t *testing.T) {
function TestDB_CreateChallenge (line 125) | func TestDB_CreateChallenge(t *testing.T) {
function TestDB_GetChallenge (line 221) | func TestDB_GetChallenge(t *testing.T) {
function TestDB_UpdateChallenge (line 317) | func TestDB_UpdateChallenge(t *testing.T) {
FILE: acme/db/nosql/eab.go
type dbExternalAccountKey (line 22) | type dbExternalAccountKey struct
type dbExternalAccountKeyReference (line 32) | type dbExternalAccountKeyReference struct
method getDBExternalAccountKey (line 38) | func (db *DB) getDBExternalAccountKey(_ context.Context, id string) (*db...
method CreateExternalAccountKey (line 56) | func (db *DB) CreateExternalAccountKey(ctx context.Context, provisionerI...
method GetExternalAccountKey (line 109) | func (db *DB) GetExternalAccountKey(ctx context.Context, provisionerID, ...
method DeleteExternalAccountKey (line 133) | func (db *DB) DeleteExternalAccountKey(ctx context.Context, provisionerI...
method GetExternalAccountKeys (line 162) | func (db *DB) GetExternalAccountKeys(ctx context.Context, provisionerID,...
method GetExternalAccountKeyByReference (line 209) | func (db *DB) GetExternalAccountKeyByReference(ctx context.Context, prov...
method GetExternalAccountKeyByAccountID (line 232) | func (db *DB) GetExternalAccountKeyByAccountID(context.Context, string, ...
method UpdateExternalAccountKey (line 237) | func (db *DB) UpdateExternalAccountKey(ctx context.Context, provisionerI...
method addEAKID (line 271) | func (db *DB) addEAKID(ctx context.Context, provisionerID, eakID string)...
method deleteEAKID (line 322) | func (db *DB) deleteEAKID(ctx context.Context, provisionerID, eakID stri...
function referenceKey (line 360) | func referenceKey(provisionerID, reference string) string {
function sliceIndex (line 365) | func sliceIndex(slice []string, item string) int {
function removeElement (line 376) | func removeElement(slice []string, item string) []string {
FILE: acme/db/nosql/eab_test.go
function TestDB_getDBExternalAccountKey (line 19) | func TestDB_getDBExternalAccountKey(t *testing.T) {
function TestDB_GetExternalAccountKey (line 123) | func TestDB_GetExternalAccountKey(t *testing.T) {
function TestDB_GetExternalAccountKeyByReference (line 240) | func TestDB_GetExternalAccountKeyByReference(t *testing.T) {
function TestDB_GetExternalAccountKeys (line 404) | func TestDB_GetExternalAccountKeys(t *testing.T) {
function TestDB_DeleteExternalAccountKey (line 614) | func TestDB_DeleteExternalAccountKey(t *testing.T) {
function TestDB_CreateExternalAccountKey (line 906) | func TestDB_CreateExternalAccountKey(t *testing.T) {
function TestDB_UpdateExternalAccountKey (line 1072) | func TestDB_UpdateExternalAccountKey(t *testing.T) {
function TestDB_addEAKID (line 1247) | func TestDB_addEAKID(t *testing.T) {
function TestDB_deleteEAKID (line 1405) | func TestDB_deleteEAKID(t *testing.T) {
function TestDB_addAndDeleteEAKID (line 1539) | func TestDB_addAndDeleteEAKID(t *testing.T) {
function Test_removeElement (line 1673) | func Test_removeElement(t *testing.T) {
FILE: acme/db/nosql/nonce.go
type dbNonce (line 15) | type dbNonce struct
method CreateNonce (line 23) | func (db *DB) CreateNonce(ctx context.Context) (acme.Nonce, error) {
method DeleteNonce (line 42) | func (db *DB) DeleteNonce(_ context.Context, nonce acme.Nonce) error {
FILE: acme/db/nosql/nonce_test.go
function TestDB_CreateNonce (line 17) | func TestDB_CreateNonce(t *testing.T) {
function TestDB_DeleteNonce (line 84) | func TestDB_DeleteNonce(t *testing.T) {
FILE: acme/db/nosql/nosql.go
type DB (line 31) | type DB struct
method save (line 53) | func (db *DB) save(_ context.Context, id string, nu, old interface{}, ...
function New (line 36) | func New(db nosqlDB.DB) (*DB, error) {
function randID (line 89) | func randID() (val string, err error) {
type Clock (line 98) | type Clock struct
method Now (line 101) | func (c *Clock) Now() time.Time {
FILE: acme/db/nosql/nosql_test.go
function TestNew (line 13) | func TestNew(t *testing.T) {
type errorThrower (line 49) | type errorThrower
method MarshalJSON (line 51) | func (et errorThrower) MarshalJSON() ([]byte, error) {
function TestDB_save (line 55) | func TestDB_save(t *testing.T) {
FILE: acme/db/nosql/order.go
type dbOrder (line 17) | type dbOrder struct
method clone (line 32) | func (a *dbOrder) clone() *dbOrder {
method getDBOrder (line 38) | func (db *DB) getDBOrder(_ context.Context, id string) (*dbOrder, error) {
method GetOrder (line 53) | func (db *DB) GetOrder(ctx context.Context, id string) (*acme.Order, err...
method CreateOrder (line 77) | func (db *DB) CreateOrder(ctx context.Context, o *acme.Order) error {
method UpdateOrder (line 109) | func (db *DB) UpdateOrder(ctx context.Context, o *acme.Order) error {
method updateAddOrderIDs (line 124) | func (db *DB) updateAddOrderIDs(ctx context.Context, accID string, inclu...
method GetOrdersByAccountID (line 187) | func (db *DB) GetOrdersByAccountID(ctx context.Context, accID string) ([...
method GetAllOrdersByAccountID (line 192) | func (db *DB) GetAllOrdersByAccountID(ctx context.Context, accID string)...
FILE: acme/db/nosql/order_test.go
function TestDB_getDBOrder (line 18) | func TestDB_getDBOrder(t *testing.T) {
function TestDB_GetOrder (line 136) | func TestDB_GetOrder(t *testing.T) {
function TestDB_UpdateOrder (line 240) | func TestDB_UpdateOrder(t *testing.T) {
function TestDB_CreateOrder (line 382) | func TestDB_CreateOrder(t *testing.T) {
function TestDB_updateAddOrderIDs (line 570) | func TestDB_updateAddOrderIDs(t *testing.T) {
FILE: acme/db/nosql/wire.go
type dbDpopToken (line 13) | type dbDpopToken struct
method getDBDpopToken (line 20) | func (db *DB) getDBDpopToken(_ context.Context, orderID string) (*dbDpop...
method GetDpopToken (line 37) | func (db *DB) GetDpopToken(ctx context.Context, orderID string) (map[str...
method CreateDpopToken (line 50) | func (db *DB) CreateDpopToken(ctx context.Context, orderID string, dpop ...
type dbOidcToken (line 68) | type dbOidcToken struct
method getDBOidcToken (line 75) | func (db *DB) getDBOidcToken(_ context.Context, orderID string) (*dbOidc...
method GetOidcToken (line 92) | func (db *DB) GetOidcToken(ctx context.Context, orderID string) (map[str...
method CreateOidcToken (line 105) | func (db *DB) CreateOidcToken(ctx context.Context, orderID string, idTok...
FILE: acme/db/nosql/wire_test.go
function TestDB_GetDpopToken (line 17) | func TestDB_GetDpopToken(t *testing.T) {
function TestDB_CreateDpopToken (line 127) | func TestDB_CreateDpopToken(t *testing.T) {
function TestDB_GetOidcToken (line 205) | func TestDB_GetOidcToken(t *testing.T) {
function TestDB_CreateOidcToken (line 316) | func TestDB_CreateOidcToken(t *testing.T) {
FILE: acme/db_test.go
function TestIsErrNotFound (line 10) | func TestIsErrNotFound(t *testing.T) {
FILE: acme/errors.go
type ProblemType (line 13) | type ProblemType
method String (line 72) | func (ap ProblemType) String() string {
constant ErrorAccountDoesNotExistType (line 17) | ErrorAccountDoesNotExistType ProblemType = iota
constant ErrorAlreadyRevokedType (line 19) | ErrorAlreadyRevokedType
constant ErrorBadAttestationStatementType (line 21) | ErrorBadAttestationStatementType
constant ErrorBadCSRType (line 23) | ErrorBadCSRType
constant ErrorBadNonceType (line 25) | ErrorBadNonceType
constant ErrorBadPublicKeyType (line 27) | ErrorBadPublicKeyType
constant ErrorBadRevocationReasonType (line 29) | ErrorBadRevocationReasonType
constant ErrorBadSignatureAlgorithmType (line 31) | ErrorBadSignatureAlgorithmType
constant ErrorCaaType (line 33) | ErrorCaaType
constant ErrorCompoundType (line 35) | ErrorCompoundType
constant ErrorConnectionType (line 37) | ErrorConnectionType
constant ErrorDNSType (line 39) | ErrorDNSType
constant ErrorExternalAccountRequiredType (line 41) | ErrorExternalAccountRequiredType
constant ErrorIncorrectResponseType (line 43) | ErrorIncorrectResponseType
constant ErrorInvalidContactType (line 45) | ErrorInvalidContactType
constant ErrorMalformedType (line 47) | ErrorMalformedType
constant ErrorOrderNotReadyType (line 49) | ErrorOrderNotReadyType
constant ErrorRateLimitedType (line 51) | ErrorRateLimitedType
constant ErrorRejectedIdentifierType (line 53) | ErrorRejectedIdentifierType
constant ErrorServerInternalType (line 55) | ErrorServerInternalType
constant ErrorTLSType (line 57) | ErrorTLSType
constant ErrorUnauthorizedType (line 59) | ErrorUnauthorizedType
constant ErrorUnsupportedContactType (line 61) | ErrorUnsupportedContactType
constant ErrorUnsupportedIdentifierType (line 63) | ErrorUnsupportedIdentifierType
constant ErrorUserActionRequiredType (line 65) | ErrorUserActionRequiredType
constant ErrorNotImplementedType (line 67) | ErrorNotImplementedType
type errorMetadata (line 129) | type errorMetadata struct
type Error (line 274) | type Error struct
method withDetail (line 308) | func (e *Error) withDetail() *Error {
method AddSubproblems (line 319) | func (e *Error) AddSubproblems(subproblems ...Subproblem) *Error {
method StatusCode (line 397) | func (e *Error) StatusCode() int {
method Error (line 402) | func (e *Error) Error() string {
method Cause (line 410) | func (e *Error) Cause() error {
method ToLog (line 418) | func (e *Error) ToLog() (any, error) {
method Render (line 427) | func (e *Error) Render(w http.ResponseWriter, r *http.Request) {
type Subproblem (line 286) | type Subproblem struct
function NewError (line 297) | func NewError(pt ProblemType, msg string, args ...any) *Error {
function NewDetailedError (line 304) | func NewDetailedError(pt ProblemType, msg string, args ...any) *Error {
function NewSubproblem (line 327) | func NewSubproblem(pt ProblemType, msg string, args ...any) Subproblem {
function NewSubproblemWithIdentifier (line 338) | func NewSubproblemWithIdentifier(pt ProblemType, identifier Identifier, ...
function newError (line 344) | func newError(pt ProblemType, err error) *Error {
function NewErrorISE (line 365) | func NewErrorISE(msg string, args ...any) *Error {
function WrapError (line 370) | func WrapError(typ ProblemType, err error, msg string, args ...any) *Err...
function WrapDetailedError (line 387) | func WrapDetailedError(typ ProblemType, err error, msg string, args ...a...
function WrapErrorISE (line 392) | func WrapErrorISE(err error, msg string, args ...any) *Error {
FILE: acme/errors_test.go
function mustJSON (line 11) | func mustJSON(t *testing.T, m map[string]interface{}) string {
function TestError_WithAdditionalErrorDetail (line 20) | func TestError_WithAdditionalErrorDetail(t *testing.T) {
FILE: acme/linker.go
type LinkType (line 18) | type LinkType
method String (line 51) | func (l LinkType) String() string {
constant NewNonceLinkType (line 22) | NewNonceLinkType LinkType = iota
constant NewAccountLinkType (line 24) | NewAccountLinkType
constant AccountLinkType (line 26) | AccountLinkType
constant OrderLinkType (line 28) | OrderLinkType
constant NewOrderLinkType (line 30) | NewOrderLinkType
constant OrdersByAccountLinkType (line 32) | OrdersByAccountLinkType
constant FinalizeLinkType (line 34) | FinalizeLinkType
constant NewAuthzLinkType (line 36) | NewAuthzLinkType
constant AuthzLinkType (line 38) | AuthzLinkType
constant ChallengeLinkType (line 40) | ChallengeLinkType
constant CertificateLinkType (line 42) | CertificateLinkType
constant DirectoryLinkType (line 44) | DirectoryLinkType
constant RevokeCertLinkType (line 46) | RevokeCertLinkType
constant KeyChangeLinkType (line 48) | KeyChangeLinkType
function GetUnescapedPathSuffix (line 82) | func GetUnescapedPathSuffix(typ LinkType, provisionerName string, inputs...
function NewLinker (line 100) | func NewLinker(dns, prefix string) Linker {
type Linker (line 119) | type Linker interface
type linkerKey (line 129) | type linkerKey struct
function NewLinkerContext (line 132) | func NewLinkerContext(ctx context.Context, v Linker) context.Context {
function LinkerFromContext (line 137) | func LinkerFromContext(ctx context.Context) (v Linker, ok bool) {
function MustLinkerFromContext (line 144) | func MustLinkerFromContext(ctx context.Context) Linker {
type baseURLKey (line 155) | type baseURLKey struct
function newBaseURLContext (line 157) | func newBaseURLContext(ctx context.Context, r *http.Request) context.Con...
function baseURLFromContext (line 165) | func baseURLFromContext(ctx context.Context) *url.URL {
type linker (line 173) | type linker struct
method Middleware (line 180) | func (l *linker) Middleware(next http.Handler) http.Handler {
method GetLink (line 217) | func (l *linker) GetLink(ctx context.Context, typ LinkType, inputs ......
method LinkOrder (line 239) | func (l *linker) LinkOrder(ctx context.Context, o *Order) {
method LinkAccount (line 251) | func (l *linker) LinkAccount(ctx context.Context, acc *Account) {
method LinkChallenge (line 256) | func (l *linker) LinkChallenge(ctx context.Context, ch *Challenge, azI...
method LinkAuthorization (line 261) | func (l *linker) LinkAuthorization(ctx context.Context, az *Authorizat...
method LinkOrdersByAccountID (line 268) | func (l *linker) LinkOrdersByAccountID(ctx context.Context, orders []s...
FILE: acme/linker_test.go
function mockProvisioner (line 14) | func mockProvisioner(t *testing.T) Provisioner {
function TestGetUnescapedPathSuffix (line 34) | func TestGetUnescapedPathSuffix(t *testing.T) {
function TestLinker_DNS (line 51) | func TestLinker_DNS(t *testing.T) {
function TestLinker_GetLink (line 131) | func TestLinker_GetLink(t *testing.T) {
function TestLinker_LinkOrder (line 181) | func TestLinker_LinkOrder(t *testing.T) {
function TestLinker_LinkAccount (line 246) | func TestLinker_LinkAccount(t *testing.T) {
function TestLinker_LinkChallenge (line 278) | func TestLinker_LinkChallenge(t *testing.T) {
function TestLinker_LinkAuthorization (line 311) | func TestLinker_LinkAuthorization(t *testing.T) {
function TestLinker_LinkOrdersByAccountID (line 353) | func TestLinker_LinkOrdersByAccountID(t *testing.T) {
FILE: acme/nonce.go
type Nonce (line 4) | type Nonce
method String (line 7) | func (n Nonce) String() string {
FILE: acme/order.go
type IdentifierType (line 26) | type IdentifierType
constant IP (line 30) | IP IdentifierType = "ip"
constant DNS (line 32) | DNS IdentifierType = "dns"
constant PermanentIdentifier (line 35) | PermanentIdentifier IdentifierType = "permanent-identifier"
constant WireUser (line 37) | WireUser IdentifierType = "wireapp-user"
constant WireDevice (line 39) | WireDevice IdentifierType = "wireapp-device"
type Identifier (line 43) | type Identifier struct
type Order (line 49) | type Order struct
method ToLog (line 67) | func (o *Order) ToLog() (interface{}, error) {
method UpdateStatus (line 77) | func (o *Order) UpdateStatus(ctx context.Context, db DB) error {
method getAuthorizationFingerprint (line 149) | func (o *Order) getAuthorizationFingerprint(ctx context.Context, db DB...
method Finalize (line 171) | func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.Certifi...
method containsWireIdentifiers (line 345) | func (o *Order) containsWireIdentifiers() bool {
method sans (line 402) | func (o *Order) sans(csr *x509.CertificateRequest) ([]x509util.Subject...
function createWireSubject (line 355) | func createWireSubject(o *Order, csr *x509.CertificateRequest) (subject ...
function numberOfIdentifierType (line 523) | func numberOfIdentifierType(typ IdentifierType, ids []Identifier) int {
function canonicalize (line 538) | func canonicalize(csr *x509.CertificateRequest) (canonicalized *x509.Cer...
function ipsAreEqual (line 570) | func ipsAreEqual(x, y net.IP) bool {
function uniqueSortedLowerNames (line 580) | func uniqueSortedLowerNames(names []string) (unique []string) {
function uniqueSortedURIStrings (line 595) | func uniqueSortedURIStrings(uris []*url.URL) (unique []string) {
function uniqueSortedIPs (line 610) | func uniqueSortedIPs(ips []net.IP) (unique []net.IP) {
FILE: acme/order_test.go
function TestOrder_UpdateStatus (line 28) | func TestOrder_UpdateStatus(t *testing.T) {
type mockSignAuth (line 275) | type mockSignAuth struct
method SignWithContext (line 283) | func (m *mockSignAuth) SignWithContext(ctx context.Context, csr *x509....
method AreSANsAllowed (line 292) | func (m *mockSignAuth) AreSANsAllowed(ctx context.Context, sans []stri...
method LoadProvisionerByName (line 299) | func (m *mockSignAuth) LoadProvisionerByName(name string) (provisioner...
method IsRevoked (line 306) | func (m *mockSignAuth) IsRevoked(string) (bool, error) {
method Revoke (line 310) | func (m *mockSignAuth) Revoke(context.Context, *authority.RevokeOption...
method GetBackdate (line 314) | func (m *mockSignAuth) GetBackdate() *time.Duration {
function TestOrder_Finalize (line 318) | func TestOrder_Finalize(t *testing.T) {
function Test_uniqueSortedIPs (line 1949) | func Test_uniqueSortedIPs(t *testing.T) {
function Test_numberOfIdentifierType (line 2045) | func Test_numberOfIdentifierType(t *testing.T) {
function Test_ipsAreEqual (line 2175) | func Test_ipsAreEqual(t *testing.T) {
function Test_canonicalize (line 2267) | func Test_canonicalize(t *testing.T) {
function TestOrder_sans (line 2380) | func TestOrder_sans(t *testing.T) {
function TestOrder_getAuthorizationFingerprint (line 2593) | func TestOrder_getAuthorizationFingerprint(t *testing.T) {
FILE: acme/status.go
type Status (line 4) | type Status
FILE: acme/wire/id.go
type UserID (line 11) | type UserID struct
type DeviceID (line 17) | type DeviceID struct
function ParseUserID (line 24) | func ParseUserID(value string) (id UserID, err error) {
function ParseDeviceID (line 41) | func ParseDeviceID(value string) (id DeviceID, err error) {
type ClientID (line 60) | type ClientID struct
function ParseClientID (line 72) | func ParseClientID(clientID string) (ClientID, error) {
FILE: acme/wire/id_test.go
function TestParseUserID (line 10) | func TestParseUserID(t *testing.T) {
function TestParseDeviceID (line 42) | func TestParseDeviceID(t *testing.T) {
function TestParseClientID (line 76) | func TestParseClientID(t *testing.T) {
FILE: api/api.go
type Authority (line 39) | type Authority interface
function NewTimeDuration (line 71) | func NewTimeDuration(t time.Time) TimeDuration {
function ParseTimeDuration (line 77) | func ParseTimeDuration(s string) (TimeDuration, error) {
type Certificate (line 82) | type Certificate struct
method reset (line 95) | func (c *Certificate) reset() {
method MarshalJSON (line 103) | func (c Certificate) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 116) | func (c *Certificate) UnmarshalJSON(data []byte) error {
function NewCertificate (line 88) | func NewCertificate(cr *x509.Certificate) Certificate {
type CertificateRequest (line 142) | type CertificateRequest struct
method reset (line 155) | func (c *CertificateRequest) reset() {
method MarshalJSON (line 163) | func (c CertificateRequest) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 176) | func (c *CertificateRequest) UnmarshalJSON(data []byte) error {
function NewCertificateRequest (line 148) | func NewCertificateRequest(cr *x509.CertificateRequest) CertificateReque...
type Router (line 201) | type Router interface
type RouterHandler (line 209) | type RouterHandler interface
type VersionResponse (line 215) | type VersionResponse struct
type HealthResponse (line 221) | type HealthResponse struct
type RootResponse (line 226) | type RootResponse struct
type ProvisionersResponse (line 232) | type ProvisionersResponse struct
method MarshalJSON (line 266) | func (p ProvisionersResponse) MarshalJSON() ([]byte, error) {
constant redacted (line 237) | redacted = "*** REDACTED ***"
function scepFromProvisioner (line 239) | func scepFromProvisioner(p *provisioner.SCEP) *models.SCEP {
type ProvisionerKeyResponse (line 291) | type ProvisionerKeyResponse struct
type RootsResponse (line 296) | type RootsResponse struct
type IntermediatesResponse (line 301) | type IntermediatesResponse struct
type FederationResponse (line 306) | type FederationResponse struct
type caHandler (line 311) | type caHandler struct
method Route (line 316) | func (h *caHandler) Route(r Router) {
function New (line 323) | func New(Authority) RouterHandler {
function Route (line 327) | func Route(r Router) {
function Version (line 364) | func Version(w http.ResponseWriter, r *http.Request) {
function Health (line 373) | func Health(w http.ResponseWriter, r *http.Request) {
function Root (line 379) | func Root(w http.ResponseWriter, r *http.Request) {
function certChainToPEM (line 392) | func certChainToPEM(certChain []*x509.Certificate) []Certificate {
function Provisioners (line 401) | func Provisioners(w http.ResponseWriter, r *http.Request) {
function ProvisionerKey (line 421) | func ProvisionerKey(w http.ResponseWriter, r *http.Request) {
function Roots (line 433) | func Roots(w http.ResponseWriter, r *http.Request) {
function RootsPEM (line 451) | func RootsPEM(w http.ResponseWriter, r *http.Request) {
function Intermediates (line 474) | func Intermediates(w http.ResponseWriter, r *http.Request) {
function IntermediatesPEM (line 492) | func IntermediatesPEM(w http.ResponseWriter, r *http.Request) {
function Federation (line 515) | func Federation(w http.ResponseWriter, r *http.Request) {
type stepProvisioner (line 534) | type stepProvisioner struct
function logOtt (line 540) | func logOtt(w http.ResponseWriter, token string) {
function LogCertificate (line 549) | func LogCertificate(w http.ResponseWriter, cert *x509.Certificate) {
function LogSSHCertificate (line 582) | func LogSSHCertificate(w http.ResponseWriter, cert *ssh.Certificate) {
function ParseCursor (line 617) | func ParseCursor(r *http.Request) (cursor string, limit int, err error) {
function fmtSans (line 629) | func fmtSans(cert *x509.Certificate) map[string][]string {
function fmtPublicKey (line 654) | func fmtPublicKey(cert *x509.Certificate) string {
FILE: api/api_test.go
constant rootPEM (line 46) | rootPEM = `-----BEGIN CERTIFICATE-----
constant certPEM (line 71) | certPEM = `-----BEGIN CERTIFICATE-----
constant csrPEM (line 94) | csrPEM = `-----BEGIN CERTIFICATE REQUEST-----
constant stepCertPEM (line 121) | stepCertPEM = `-----BEGIN CERTIFICATE-----
constant pubKey (line 138) | pubKey = `{
constant privKey (line 148) | privKey = "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsI...
function mustJSON (line 151) | func mustJSON(t *testing.T, v any) []byte {
function parseCertificate (line 158) | func parseCertificate(data string) *x509.Certificate {
function parseCertificateRequest (line 170) | func parseCertificateRequest(data string) *x509.CertificateRequest {
function mockMustAuthority (line 182) | func mockMustAuthority(t *testing.T, a Authority) {
type mockAuthority (line 193) | type mockAuthority struct
method GetCertificateRevocationList (line 226) | func (m *mockAuthority) GetCertificateRevocationList() (*authority.Cer...
method Authorize (line 235) | func (m *mockAuthority) Authorize(ctx context.Context, ott string) ([]...
method AuthorizeRenewToken (line 242) | func (m *mockAuthority) AuthorizeRenewToken(ctx context.Context, ott s...
method GetTLSOptions (line 249) | func (m *mockAuthority) GetTLSOptions() *authority.TLSOptions {
method Root (line 256) | func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) {
method SignWithContext (line 263) | func (m *mockAuthority) SignWithContext(ctx context.Context, cr *x509....
method Renew (line 270) | func (m *mockAuthority) Renew(cert *x509.Certificate) ([]*x509.Certifi...
method RenewContext (line 277) | func (m *mockAuthority) RenewContext(ctx context.Context, oldcert *x50...
method Rekey (line 284) | func (m *mockAuthority) Rekey(oldcert *x509.Certificate, pk crypto.Pub...
method GetProvisioners (line 291) | func (m *mockAuthority) GetProvisioners(nextCursor string, limit int) ...
method LoadProvisionerByCertificate (line 298) | func (m *mockAuthority) LoadProvisionerByCertificate(cert *x509.Certif...
method LoadProvisionerByName (line 305) | func (m *mockAuthority) LoadProvisionerByName(name string) (provisione...
method Revoke (line 312) | func (m *mockAuthority) Revoke(ctx context.Context, opts *authority.Re...
method GetEncryptedKey (line 319) | func (m *mockAuthority) GetEncryptedKey(kid string) (string, error) {
method GetRoots (line 326) | func (m *mockAuthority) GetRoots() ([]*x509.Certificate, error) {
method GetIntermediateCertificates (line 333) | func (m *mockAuthority) GetIntermediateCertificates() []*x509.Certific...
method GetFederation (line 340) | func (m *mockAuthority) GetFederation() ([]*x509.Certificate, error) {
method SignSSH (line 347) | func (m *mockAuthority) SignSSH(ctx context.Context, key ssh.PublicKey...
method SignSSHAddUser (line 354) | func (m *mockAuthority) SignSSHAddUser(ctx context.Context, key ssh.Pu...
method RenewSSH (line 361) | func (m *mockAuthority) RenewSSH(ctx context.Context, cert *ssh.Certif...
method RekeySSH (line 368) | func (m *mockAuthority) RekeySSH(ctx context.Context, cert *ssh.Certif...
method GetSSHHosts (line 375) | func (m *mockAuthority) GetSSHHosts(ctx context.Context, cert *x509.Ce...
method GetSSHRoots (line 382) | func (m *mockAuthority) GetSSHRoots(ctx context.Context) (*authority.S...
method GetSSHFederation (line 389) | func (m *mockAuthority) GetSSHFederation(ctx context.Context) (*author...
method GetSSHConfig (line 396) | func (m *mockAuthority) GetSSHConfig(ctx context.Context, typ string, ...
method CheckSSHHost (line 403) | func (m *mockAuthority) CheckSSHHost(ctx context.Context, principal, t...
method GetSSHBastion (line 410) | func (m *mockAuthority) GetSSHBastion(ctx context.Context, user, hostn...
method Version (line 417) | func (m *mockAuthority) Version() authority.Version {
function TestNewCertificate (line 424) | func TestNewCertificate(t *testing.T) {
function TestCertificate_MarshalJSON (line 431) | func TestCertificate_MarshalJSON(t *testing.T) {
function TestCertificate_UnmarshalJSON (line 464) | func TestCertificate_UnmarshalJSON(t *testing.T) {
function TestCertificate_UnmarshalJSON_json (line 495) | func TestCertificate_UnmarshalJSON_json(t *testing.T) {
function TestNewCertificateRequest (line 535) | func TestNewCertificateRequest(t *testing.T) {
function TestCertificateRequest_MarshalJSON (line 542) | func TestCertificateRequest_MarshalJSON(t *testing.T) {
function TestCertificateRequest_UnmarshalJSON (line 574) | func TestCertificateRequest_UnmarshalJSON(t *testing.T) {
function TestCertificateRequest_UnmarshalJSON_json (line 604) | func TestCertificateRequest_UnmarshalJSON_json(t *testing.T) {
function TestSignRequest_Validate (line 645) | func TestSignRequest_Validate(t *testing.T) {
type mockProvisioner (line 683) | type mockProvisioner struct
method GetID (line 703) | func (m *mockProvisioner) GetID() string {
method GetIDForToken (line 710) | func (m *mockProvisioner) GetIDForToken() string {
method GetTokenID (line 717) | func (m *mockProvisioner) GetTokenID(token string) (string, error) {
method GetName (line 727) | func (m *mockProvisioner) GetName() string {
method GetType (line 734) | func (m *mockProvisioner) GetType() provisioner.Type {
method GetEncryptedKey (line 741) | func (m *mockProvisioner) GetEncryptedKey() (string, string, bool) {
method Init (line 748) | func (m *mockProvisioner) Init(c provisioner.Config) error {
method AuthorizeRenew (line 755) | func (m *mockProvisioner) AuthorizeRenew(ctx context.Context, cert *x5...
method AuthorizeRevoke (line 762) | func (m *mockProvisioner) AuthorizeRevoke(ctx context.Context, token s...
method AuthorizeSign (line 769) | func (m *mockProvisioner) AuthorizeSign(ctx context.Context, ott strin...
method AuthorizeRenewal (line 776) | func (m *mockProvisioner) AuthorizeRenewal(c *x509.Certificate) error {
method AuthorizeSSHSign (line 783) | func (m *mockProvisioner) AuthorizeSSHSign(ctx context.Context, token ...
method AuthorizeSSHRevoke (line 789) | func (m *mockProvisioner) AuthorizeSSHRevoke(ctx context.Context, toke...
method AuthorizeSSHRenew (line 795) | func (m *mockProvisioner) AuthorizeSSHRenew(ctx context.Context, token...
method AuthorizeSSHRekey (line 801) | func (m *mockProvisioner) AuthorizeSSHRekey(ctx context.Context, token...
function Test_caHandler_Route (line 808) | func Test_caHandler_Route(t *testing.T) {
function Test_Health (line 832) | func Test_Health(t *testing.T) {
function Test_Root (line 853) | func Test_Root(t *testing.T) {
function Test_Sign (line 901) | func Test_Sign(t *testing.T) {
function Test_Renew (line 970) | func Test_Renew(t *testing.T) {
function Test_Rekey (line 1115) | func Test_Rekey(t *testing.T) {
function Test_Provisioners (line 1176) | func Test_Provisioners(t *testing.T) {
function Test_ProvisionerKey (line 1278) | func Test_ProvisionerKey(t *testing.T) {
function Test_Roots (line 1336) | func Test_Roots(t *testing.T) {
function Test_caHandler_RootsPEM (line 1382) | func Test_caHandler_RootsPEM(t *testing.T) {
function Test_Federation (line 1422) | func Test_Federation(t *testing.T) {
function Test_fmtPublicKey (line 1468) | func Test_fmtPublicKey(t *testing.T) {
function mustCertificate (line 1519) | func mustCertificate(t *testing.T, pub, priv interface{}) *x509.Certific...
function TestProvisionersResponse_MarshalJSON (line 1545) | func TestProvisionersResponse_MarshalJSON(t *testing.T) {
constant fixtureECDSACertificate (line 1655) | fixtureECDSACertificate = `ecdsa-sha2-nistp256-cert-v01@openssh.com AAAA...
function TestLogSSHCertificate (line 1658) | func TestLogSSHCertificate(t *testing.T) {
function TestIntermediates (line 1682) | func TestIntermediates(t *testing.T) {
function TestIntermediatesPEM (line 1721) | func TestIntermediatesPEM(t *testing.T) {
FILE: api/crl.go
function CRL (line 13) | func CRL(w http.ResponseWriter, r *http.Request) {
FILE: api/crl_test.go
function Test_CRL (line 21) | func Test_CRL(t *testing.T) {
FILE: api/log/log.go
type errorLoggerKey (line 13) | type errorLoggerKey struct
type ErrorLogger (line 16) | type ErrorLogger
method call (line 18) | func (fn ErrorLogger) call(w http.ResponseWriter, r *http.Request, err...
function WithErrorLogger (line 26) | func WithErrorLogger(ctx context.Context, fn ErrorLogger) context.Context {
function ErrorLoggerFromContext (line 31) | func ErrorLoggerFromContext(ctx context.Context) (fn ErrorLogger) {
type StackTracedError (line 40) | type StackTracedError interface
type fieldCarrier (line 46) | type fieldCarrier interface
function Error (line 54) | func Error(w http.ResponseWriter, r *http.Request, err error) {
function EnabledResponse (line 80) | func EnabledResponse(rw http.ResponseWriter, r *http.Request, v any) {
FILE: api/log/log_test.go
type stackTracedError (line 18) | type stackTracedError struct
method Error (line 20) | func (stackTracedError) Error() string {
method StackTrace (line 24) | func (stackTracedError) StackTrace() pkgerrors.StackTrace {
function TestError (line 32) | func TestError(t *testing.T) {
FILE: api/models/scep.go
type SCEP (line 18) | type SCEP struct
method GetID (line 38) | func (s *SCEP) GetID() string {
method GetIDForToken (line 47) | func (s *SCEP) GetIDForToken() string {
method GetName (line 52) | func (s *SCEP) GetName() string {
method GetType (line 57) | func (s *SCEP) GetType() provisioner.Type {
method GetEncryptedKey (line 62) | func (s *SCEP) GetEncryptedKey() (string, string, bool) {
method GetTokenID (line 67) | func (s *SCEP) GetTokenID(string) (string, error) {
method Init (line 72) | func (s *SCEP) Init(_ provisioner.Config) (err error) {
method AuthorizeSign (line 78) | func (s *SCEP) AuthorizeSign(context.Context, string) ([]provisioner.S...
method AuthorizeRevoke (line 84) | func (s *SCEP) AuthorizeRevoke(context.Context, string) error {
method AuthorizeRenew (line 90) | func (s *SCEP) AuthorizeRenew(context.Context, *x509.Certificate) error {
method AuthorizeSSHSign (line 96) | func (s *SCEP) AuthorizeSSHSign(context.Context, string) ([]provisione...
method AuthorizeSSHRevoke (line 102) | func (s *SCEP) AuthorizeSSHRevoke(context.Context, string) error {
method AuthorizeSSHRenew (line 108) | func (s *SCEP) AuthorizeSSHRenew(context.Context, string) (*ssh.Certif...
method AuthorizeSSHRekey (line 114) | func (s *SCEP) AuthorizeSSHRekey(context.Context, string) (*ssh.Certif...
FILE: api/read/read.go
function JSON (line 20) | func JSON(r io.Reader, v interface{}) error {
function ProtoJSON (line 29) | func ProtoJSON(r io.Reader, m proto.Message) error {
type badProtoJSONError (line 46) | type badProtoJSONError
method Error (line 49) | func (e badProtoJSONError) Error() string {
method Render (line 54) | func (e badProtoJSONError) Render(w http.ResponseWriter, r *http.Reque...
FILE: api/read/read_test.go
function TestJSON (line 23) | func TestJSON(t *testing.T) {
function TestProtoJSON (line 59) | func TestProtoJSON(t *testing.T) {
function Test_badProtoJSONError_Render (line 124) | func Test_badProtoJSONError_Render(t *testing.T) {
FILE: api/rekey.go
type RekeyRequest (line 12) | type RekeyRequest struct
method Validate (line 18) | func (s *RekeyRequest) Validate() error {
function Rekey (line 30) | func Rekey(w http.ResponseWriter, r *http.Request) {
FILE: api/render/render.go
function JSON (line 16) | func JSON(w http.ResponseWriter, r *http.Request, v interface{}) {
function JSONStatus (line 25) | func JSONStatus(w http.ResponseWriter, r *http.Request, v interface{}, s...
function ProtoJSON (line 50) | func ProtoJSON(w http.ResponseWriter, m proto.Message) {
function ProtoJSONStatus (line 56) | func ProtoJSONStatus(w http.ResponseWriter, m proto.Message, status int) {
function setContentTypeUnlessPresent (line 67) | func setContentTypeUnlessPresent(w http.ResponseWriter, contentType stri...
type RenderableError (line 80) | type RenderableError interface
function Error (line 88) | func Error(rw http.ResponseWriter, r *http.Request, err error) {
type StatusCodedError (line 106) | type StatusCodedError interface
function statusCodeFromError (line 112) | func statusCodeFromError(err error) (code int) {
FILE: api/render/render_test.go
function TestJSON (line 18) | func TestJSON(t *testing.T) {
function TestJSONPanicsOnUnsupportedType (line 31) | func TestJSONPanicsOnUnsupportedType(t *testing.T) {
function TestJSONPanicsOnUnsupportedValue (line 35) | func TestJSONPanicsOnUnsupportedValue(t *testing.T) {
function TestJSONPanicsOnMarshalerError (line 39) | func TestJSONPanicsOnMarshalerError(t *testing.T) {
type erroneousJSONMarshaler (line 44) | type erroneousJSONMarshaler struct
method MarshalJSON (line 46) | func (erroneousJSONMarshaler) MarshalJSON() ([]byte, error) {
function jsonPanicTest (line 50) | func jsonPanicTest[T json.UnsupportedTypeError | json.UnsupportedValueEr...
type renderableError (line 71) | type renderableError struct
method Error (line 76) | func (err renderableError) Error() string {
method Render (line 80) | func (err renderableError) Render(w http.ResponseWriter, r *http.Reque...
type statusedError (line 85) | type statusedError struct
method Error (line 89) | func (err statusedError) Error() string { return err.Contents }
method StatusCode (line 91) | func (statusedError) StatusCode() int { return 432 }
function TestError (line 93) | func TestError(t *testing.T) {
type causedError (line 129) | type causedError struct
method Error (line 133) | func (err causedError) Error() string { return fmt.Sprintf("cause: %s"...
method Cause (line 134) | func (err causedError) Cause() error { return err.cause }
function TestStatusCodeFromError (line 136) | func TestStatusCodeFromError(t *testing.T) {
FILE: api/renew.go
constant authorizationHeader (line 15) | authorizationHeader = "Authorization"
constant bearerScheme (line 16) | bearerScheme = "Bearer"
function Renew (line 21) | func Renew(w http.ResponseWriter, r *http.Request) {
function getPeerCertificate (line 58) | func getPeerCertificate(r *http.Request) (*x509.Certificate, string, err...
FILE: api/revoke.go
type RevokeResponse (line 18) | type RevokeResponse struct
type RevokeRequest (line 23) | type RevokeRequest struct
method Validate (line 33) | func (r *RevokeRequest) Validate() (err error) {
function Revoke (line 57) | func Revoke(w http.ResponseWriter, r *http.Request) {
function logRevoke (line 118) | func logRevoke(w http.ResponseWriter, ri *authority.RevokeOptions) {
FILE: api/revoke_test.go
function TestRevokeRequestValidate (line 24) | func TestRevokeRequestValidate(t *testing.T) {
function Test_caHandler_Revoke (line 79) | func Test_caHandler_Revoke(t *testing.T) {
FILE: api/sign.go
type SignRequest (line 16) | type SignRequest struct
method Validate (line 26) | func (s *SignRequest) Validate() error {
type SignResponse (line 41) | type SignResponse struct
function Sign (line 52) | func Sign(w http.ResponseWriter, r *http.Request) {
FILE: api/ssh.go
type SSHAuthority (line 28) | type SSHAuthority interface
type SSHSignRequest (line 42) | type SSHSignRequest struct
method Validate (line 56) | func (s *SSHSignRequest) Validate() error {
type SSHSignResponse (line 76) | type SSHSignResponse struct
type SSHRootsResponse (line 84) | type SSHRootsResponse struct
type SSHCertificate (line 90) | type SSHCertificate struct
method MarshalJSON (line 102) | func (c SSHCertificate) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 112) | func (c *SSHCertificate) UnmarshalJSON(data []byte) error {
type SSHGetHostsResponse (line 96) | type SSHGetHostsResponse struct
type SSHPublicKey (line 138) | type SSHPublicKey struct
method MarshalJSON (line 144) | func (p *SSHPublicKey) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 155) | func (p *SSHPublicKey) UnmarshalJSON(data []byte) error {
type SSHConfigRequest (line 181) | type SSHConfigRequest struct
method Validate (line 187) | func (r *SSHConfigRequest) Validate() error {
type SSHConfigResponse (line 200) | type SSHConfigResponse struct
type SSHCheckPrincipalRequest (line 208) | type SSHCheckPrincipalRequest struct
method Validate (line 215) | func (r *SSHCheckPrincipalRequest) Validate() error {
type SSHCheckPrincipalResponse (line 228) | type SSHCheckPrincipalResponse struct
type SSHBastionRequest (line 234) | type SSHBastionRequest struct
method Validate (line 240) | func (r *SSHBastionRequest) Validate() error {
type SSHBastionResponse (line 249) | type SSHBastionResponse struct
function SSHSign (line 257) | func SSHSign(w http.ResponseWriter, r *http.Request) {
function SSHRoots (line 357) | func SSHRoots(w http.ResponseWriter, r *http.Request) {
function SSHFederation (line 383) | func SSHFederation(w http.ResponseWriter, r *http.Request) {
function SSHConfig (line 409) | func SSHConfig(w http.ResponseWriter, r *http.Request) {
function SSHCheckHost (line 442) | func SSHCheckHost(w http.ResponseWriter, r *http.Request) {
function SSHGetHosts (line 465) | func SSHGetHosts(w http.ResponseWriter, r *http.Request) {
function SSHBastion (line 483) | func SSHBastion(w http.ResponseWriter, r *http.Request) {
type identityModifier (line 509) | type identityModifier struct
method Enforce (line 517) | func (m *identityModifier) Enforce(cert *x509.Certificate) error {
function getIdentityURI (line 534) | func getIdentityURI(cr *x509.CertificateRequest) *url.URL {
FILE: api/sshRekey.go
type SSHRekeyRequest (line 17) | type SSHRekeyRequest struct
method Validate (line 23) | func (s *SSHRekeyRequest) Validate() error {
type SSHRekeyResponse (line 35) | type SSHRekeyResponse struct
function SSHRekey (line 43) | func SSHRekey(w http.ResponseWriter, r *http.Request) {
FILE: api/sshRenew.go
type SSHRenewRequest (line 18) | type SSHRenewRequest struct
method Validate (line 23) | func (s *SSHRenewRequest) Validate() error {
type SSHRenewResponse (line 33) | type SSHRenewResponse struct
function SSHRenew (line 41) | func SSHRenew(w http.ResponseWriter, r *http.Request) {
function renewIdentityCertificate (line 93) | func renewIdentityCertificate(r *http.Request, notBefore, notAfter time....
FILE: api/sshRevoke.go
type SSHRevokeResponse (line 17) | type SSHRevokeResponse struct
type SSHRevokeRequest (line 22) | type SSHRevokeRequest struct
method Validate (line 32) | func (r *SSHRevokeRequest) Validate() (err error) {
function SSHRevoke (line 51) | func SSHRevoke(w http.ResponseWriter, r *http.Request) {
function logSSHRevoke (line 91) | func logSSHRevoke(w http.ResponseWriter, ri *authority.RevokeOptions) {
FILE: api/ssh_test.go
function mustKey (line 38) | func mustKey() *ecdsa.PrivateKey {
function signSSHCertificate (line 46) | func signSSHCertificate(cert *ssh.Certificate) error {
function getSignedUserCertificate (line 66) | func getSignedUserCertificate() (*ssh.Certificate, error) {
function getSignedHostCertificate (line 99) | func getSignedHostCertificate() (*ssh.Certificate, error) {
function TestSSHCertificate_MarshalJSON (line 126) | func TestSSHCertificate_MarshalJSON(t *testing.T) {
function TestSSHCertificate_UnmarshalJSON (line 164) | func TestSSHCertificate_UnmarshalJSON(t *testing.T) {
function TestSignSSHRequest_Validate (line 204) | func TestSignSSHRequest_Validate(t *testing.T) {
function Test_SSHSign (line 256) | func Test_SSHSign(t *testing.T) {
function Test_SSHRoots (line 358) | func Test_SSHRoots(t *testing.T) {
function Test_SSHFederation (line 412) | func Test_SSHFederation(t *testing.T) {
function Test_SSHConfig (line 466) | func Test_SSHConfig(t *testing.T) {
function Test_SSHCheckHost (line 526) | func Test_SSHCheckHost(t *testing.T) {
function Test_SSHGetHosts (line 573) | func Test_SSHGetHosts(t *testing.T) {
function Test_SSHBastion (line 624) | func Test_SSHBastion(t *testing.T) {
function TestSSHPublicKey_MarshalJSON (line 679) | func TestSSHPublicKey_MarshalJSON(t *testing.T) {
function TestSSHPublicKey_UnmarshalJSON (line 708) | func TestSSHPublicKey_UnmarshalJSON(t *testing.T) {
function Test_identityModifier_Enforce (line 742) | func Test_identityModifier_Enforce(t *testing.T) {
function Test_getIdentityURI (line 802) | func Test_getIdentityURI(t *testing.T) {
FILE: authority/admin/api/acme.go
type CreateExternalAccountKeyRequest (line 16) | type CreateExternalAccountKeyRequest struct
method Validate (line 21) | func (r *CreateExternalAccountKeyRequest) Validate() error {
type GetExternalAccountKeysResponse (line 29) | type GetExternalAccountKeysResponse struct
function requireEABEnabled (line 36) | func requireEABEnabled(next http.HandlerFunc) http.HandlerFunc {
type ACMEAdminResponder (line 57) | type ACMEAdminResponder interface
type acmeAdminResponder (line 64) | type acmeAdminResponder struct
method GetExternalAccountKeys (line 72) | func (h *acmeAdminResponder) GetExternalAccountKeys(w http.ResponseWri...
method CreateExternalAccountKey (line 77) | func (h *acmeAdminResponder) CreateExternalAccountKey(w http.ResponseW...
method DeleteExternalAccountKey (line 82) | func (h *acmeAdminResponder) DeleteExternalAccountKey(w http.ResponseW...
function NewACMEAdminResponder (line 67) | func NewACMEAdminResponder() ACMEAdminResponder {
function eakToLinked (line 86) | func eakToLinked(k *acme.ExternalAccountKey) *linkedca.EABKey {
function linkedEAKToCertificates (line 118) | func linkedEAKToCertificates(k *linkedca.EABKey) *acme.ExternalAccountKey {
FILE: authority/admin/api/acme_test.go
function readProtoJSON (line 27) | func readProtoJSON(r io.ReadCloser, m proto.Message) error {
function mockMustAuthority (line 36) | func mockMustAuthority(t *testing.T, a adminAuthority) {
function TestHandler_requireEABEnabled (line 47) | func TestHandler_requireEABEnabled(t *testing.T) {
function TestCreateExternalAccountKeyRequest_Validate (line 157) | func TestCreateExternalAccountKeyRequest_Validate(t *testing.T) {
function TestHandler_CreateExternalAccountKey (line 200) | func TestHandler_CreateExternalAccountKey(t *testing.T) {
function TestHandler_DeleteExternalAccountKey (line 251) | func TestHandler_DeleteExternalAccountKey(t *testing.T) {
function TestHandler_GetExternalAccountKeys (line 303) | func TestHandler_GetExternalAccountKeys(t *testing.T) {
function Test_eakToLinked (line 357) | func Test_eakToLinked(t *testing.T) {
function Test_linkedEAKToCertificates (line 446) | func Test_linkedEAKToCertificates(t *testing.T) {
FILE: authority/admin/api/admin.go
type adminAuthority (line 18) | type adminAuthority interface
type CreateAdminRequest (line 39) | type CreateAdminRequest struct
method Validate (line 46) | func (car *CreateAdminRequest) Validate() error {
type GetAdminsResponse (line 62) | type GetAdminsResponse struct
type UpdateAdminRequest (line 68) | type UpdateAdminRequest struct
method Validate (line 73) | func (uar *UpdateAdminRequest) Validate() error {
type DeleteResponse (line 83) | type DeleteResponse struct
function GetAdmin (line 88) | func GetAdmin(w http.ResponseWriter, r *http.Request) {
function GetAdmins (line 101) | func GetAdmins(w http.ResponseWriter, r *http.Request) {
function CreateAdmin (line 121) | func CreateAdmin(w http.ResponseWriter, r *http.Request) {
function DeleteAdmin (line 154) | func DeleteAdmin(w http.ResponseWriter, r *http.Request) {
function UpdateAdmin (line 166) | func UpdateAdmin(w http.ResponseWriter, r *http.Request) {
FILE: authority/admin/api/admin_test.go
type mockAdminAuthority (line 26) | type mockAdminAuthority struct
method IsAdminAPIEnabled (line 49) | func (m *mockAdminAuthority) IsAdminAPIEnabled() bool {
method LoadProvisionerByName (line 56) | func (m *mockAdminAuthority) LoadProvisionerByName(name string) (provi...
method GetProvisioners (line 63) | func (m *mockAdminAuthority) GetProvisioners(nextCursor string, limit ...
method LoadAdminByID (line 70) | func (m *mockAdminAuthority) LoadAdminByID(id string) (*linkedca.Admin...
method GetAdmins (line 77) | func (m *mockAdminAuthority) GetAdmins(cursor string, limit int) ([]*l...
method StoreAdmin (line 84) | func (m *mockAdminAuthority) StoreAdmin(ctx context.Context, adm *link...
method UpdateAdmin (line 91) | func (m *mockAdminAuthority) UpdateAdmin(ctx context.Context, id strin...
method RemoveAdmin (line 98) | func (m *mockAdminAuthority) RemoveAdmin(ctx context.Context, id strin...
method AuthorizeAdminToken (line 105) | func (m *mockAdminAuthority) AuthorizeAdminToken(r *http.Request, toke...
method StoreProvisioner (line 112) | func (m *mockAdminAuthority) StoreProvisioner(ctx context.Context, pro...
method LoadProvisionerByID (line 119) | func (m *mockAdminAuthority) LoadProvisionerByID(id string) (provision...
method UpdateProvisioner (line 126) | func (m *mockAdminAuthority) UpdateProvisioner(ctx context.Context, nu...
method RemoveProvisioner (line 133) | func (m *mockAdminAuthority) RemoveProvisioner(ctx context.Context, id...
method GetAuthorityPolicy (line 140) | func (m *mockAdminAuthority) GetAuthorityPolicy(ctx context.Context) (...
method CreateAuthorityPolicy (line 147) | func (m *mockAdminAuthority) CreateAuthorityPolicy(ctx context.Context...
method UpdateAuthorityPolicy (line 154) | func (m *mockAdminAuthority) UpdateAuthorityPolicy(ctx context.Context...
method RemoveAuthorityPolicy (line 161) | func (m *mockAdminAuthority) RemoveAuthorityPolicy(ctx context.Context...
function TestCreateAdminRequest_Validate (line 168) | func TestCreateAdminRequest_Validate(t *testing.T) {
function TestUpdateAdminRequest_Validate (line 244) | func TestUpdateAdminRequest_Validate(t *testing.T) {
function TestHandler_GetAdmin (line 295) | func TestHandler_GetAdmin(t *testing.T) {
function TestHandler_GetAdmins (line 398) | func TestHandler_GetAdmins(t *testing.T) {
function TestHandler_CreateAdmin (line 531) | func TestHandler_CreateAdmin(t *testing.T) {
function TestHandler_DeleteAdmin (line 715) | func TestHandler_DeleteAdmin(t *testing.T) {
function TestHandler_UpdateAdmin (line 803) | func TestHandler_UpdateAdmin(t *testing.T) {
FILE: authority/admin/api/handler.go
type router (line 15) | type router struct
type RouterOption (line 21) | type RouterOption
function WithACMEResponder (line 23) | func WithACMEResponder(acmeResponder ACMEAdminResponder) RouterOption {
function WithPolicyResponder (line 29) | func WithPolicyResponder(policyResponder PolicyAdminResponder) RouterOpt...
function WithWebhookResponder (line 35) | func WithWebhookResponder(webhookResponder WebhookAdminResponder) Router...
function Route (line 42) | func Route(r api.Router, options ...RouterOption) {
FILE: authority/admin/api/middleware.go
function requireAPIEnabled (line 19) | func requireAPIEnabled(next http.HandlerFunc) http.HandlerFunc {
function extractAuthorizeTokenAdmin (line 30) | func extractAuthorizeTokenAdmin(next http.HandlerFunc) http.HandlerFunc {
function loadProvisionerByName (line 53) | func loadProvisionerByName(next http.HandlerFunc) http.HandlerFunc {
function checkAction (line 83) | func checkAction(next http.HandlerFunc, supportedInStandalone bool) http...
function loadExternalAccountKey (line 106) | func loadExternalAccountKey(next http.HandlerFunc) http.HandlerFunc {
FILE: authority/admin/api/middleware_test.go
function TestHandler_requireAPIEnabled (line 28) | func TestHandler_requireAPIEnabled(t *testing.T) {
function TestHandler_extractAuthorizeTokenAdmin (line 105) | func TestHandler_extractAuthorizeTokenAdmin(t *testing.T) {
function TestHandler_loadProvisionerByName (line 224) | func TestHandler_loadProvisionerByName(t *testing.T) {
function TestHandler_checkAction (line 355) | func TestHandler_checkAction(t *testing.T) {
function TestHandler_loadExternalAccountKey (line 428) | func TestHandler_loadExternalAccountKey(t *testing.T) {
FILE: authority/admin/api/policy.go
type PolicyAdminResponder (line 20) | type PolicyAdminResponder interface
type policyAdminResponder (line 36) | type policyAdminResponder struct
method GetAuthorityPolicy (line 44) | func (par *policyAdminResponder) GetAuthorityPolicy(w http.ResponseWri...
method CreateAuthorityPolicy (line 68) | func (par *policyAdminResponder) CreateAuthorityPolicy(w http.Response...
method UpdateAuthorityPolicy (line 120) | func (par *policyAdminResponder) UpdateAuthorityPolicy(w http.Response...
method DeleteAuthorityPolicy (line 171) | func (par *policyAdminResponder) DeleteAuthorityPolicy(w http.Response...
method GetProvisionerPolicy (line 201) | func (par *policyAdminResponder) GetProvisionerPolicy(w http.ResponseW...
method CreateProvisionerPolicy (line 219) | func (par *policyAdminResponder) CreateProvisionerPolicy(w http.Respon...
method UpdateProvisionerPolicy (line 263) | func (par *policyAdminResponder) UpdateProvisionerPolicy(w http.Respon...
method DeleteProvisionerPolicy (line 306) | func (par *policyAdminResponder) DeleteProvisionerPolicy(w http.Respon...
method GetACMEAccountPolicy (line 331) | func (par *policyAdminResponder) GetACMEAccountPolicy(w http.ResponseW...
method CreateACMEAccountPolicy (line 348) | func (par *policyAdminResponder) CreateACMEAccountPolicy(w http.Respon...
method UpdateACMEAccountPolicy (line 389) | func (par *policyAdminResponder) UpdateACMEAccountPolicy(w http.Respon...
method DeleteACMEAccountPolicy (line 428) | func (par *policyAdminResponder) DeleteACMEAccountPolicy(w http.Respon...
function NewPolicyAdminResponder (line 39) | func NewPolicyAdminResponder() PolicyAdminResponder {
function blockLinkedCA (line 457) | func blockLinkedCA(ctx context.Context) error {
function isBadRequest (line 468) | func isBadRequest(err error) bool {
function validatePolicy (line 474) | func validatePolicy(p *linkedca.Policy) error {
FILE: authority/admin/api/policy_test.go
type fakeLinkedCA (line 24) | type fakeLinkedCA struct
method IsLinkedCA (line 28) | func (f *fakeLinkedCA) IsLinkedCA() bool {
type testAdminError (line 34) | type testAdminError struct
type testX509Policy (line 40) | type testX509Policy struct
type testX509Names (line 46) | type testX509Names struct
type testSSHPolicy (line 54) | type testSSHPolicy struct
type testSSHHostPolicy (line 59) | type testSSHHostPolicy struct
type testSSHHostNames (line 64) | type testSSHHostNames struct
type testSSHUserPolicy (line 70) | type testSSHUserPolicy struct
type testSSHUserNames (line 75) | type testSSHUserNames struct
type testPolicyResponse (line 81) | type testPolicyResponse struct
function TestPolicyAdminResponder_GetAuthorityPolicy (line 86) | func TestPolicyAdminResponder_GetAuthorityPolicy(t *testing.T) {
function TestPolicyAdminResponder_CreateAuthorityPolicy (line 280) | func TestPolicyAdminResponder_CreateAuthorityPolicy(t *testing.T) {
function TestPolicyAdminResponder_UpdateAuthorityPolicy (line 571) | func TestPolicyAdminResponder_UpdateAuthorityPolicy(t *testing.T) {
function TestPolicyAdminResponder_DeleteAuthorityPolicy (line 877) | func TestPolicyAdminResponder_DeleteAuthorityPolicy(t *testing.T) {
function TestPolicyAdminResponder_GetProvisionerPolicy (line 1029) | func TestPolicyAdminResponder_GetProvisionerPolicy(t *testing.T) {
function TestPolicyAdminResponder_CreateProvisionerPolicy (line 1204) | func TestPolicyAdminResponder_CreateProvisionerPolicy(t *testing.T) {
function TestPolicyAdminResponder_UpdateProvisionerPolicy (line 1457) | func TestPolicyAdminResponder_UpdateProvisionerPolicy(t *testing.T) {
function TestPolicyAdminResponder_DeleteProvisionerPolicy (line 1721) | func TestPolicyAdminResponder_DeleteProvisionerPolicy(t *testing.T) {
function TestPolicyAdminResponder_GetACMEAccountPolicy (line 1842) | func TestPolicyAdminResponder_GetACMEAccountPolicy(t *testing.T) {
function TestPolicyAdminResponder_CreateACMEAccountPolicy (line 2026) | func TestPolicyAdminResponder_CreateACMEAccountPolicy(t *testing.T) {
function TestPolicyAdminResponder_UpdateACMEAccountPolicy (line 2253) | func TestPolicyAdminResponder_UpdateACMEAccountPolicy(t *testing.T) {
function TestPolicyAdminResponder_DeleteACMEAccountPolicy (line 2490) | func TestPolicyAdminResponder_DeleteACMEAccountPolicy(t *testing.T) {
function Test_isBadRequest (line 2641) | func Test_isBadRequest(t *testing.T) {
function Test_validatePolicy (line 2683) | func Test_validatePolicy(t *testing.T) {
FILE: authority/admin/api/provisioner.go
type GetProvisionersResponse (line 23) | type GetProvisionersResponse struct
function GetProvisioner (line 29) | func GetProvisioner(w http.ResponseWriter, r *http.Request) {
function GetProvisioners (line 62) | func GetProvisioners(w http.ResponseWriter, r *http.Request) {
function CreateProvisioner (line 82) | func CreateProvisioner(w http.ResponseWriter, r *http.Request) {
function DeleteProvisioner (line 109) | func DeleteProvisioner(w http.ResponseWriter, r *http.Request) {
function UpdateProvisioner (line 140) | func UpdateProvisioner(w http.ResponseWriter, r *http.Request) {
function validateTemplates (line 205) | func validateTemplates(x509, ssh *linkedca.Template) error {
FILE: authority/admin/api/provisioner_test.go
function TestHandler_GetProvisioner (line 28) | func TestHandler_GetProvisioner(t *testing.T) {
function TestHandler_GetProvisioners (line 200) | func TestHandler_GetProvisioners(t *testing.T) {
function TestHandler_CreateProvisioner (line 324) | func TestHandler_CreateProvisioner(t *testing.T) {
function TestHandler_DeleteProvisioner (line 474) | func TestHandler_DeleteProvisioner(t *testing.T) {
function TestHandler_UpdateProvisioner (line 629) | func TestHandler_UpdateProvisioner(t *testing.T) {
function Test_validateTemplates (line 1189) | func Test_validateTemplates(t *testing.T) {
FILE: authority/admin/api/webhook.go
type WebhookAdminResponder (line 19) | type WebhookAdminResponder interface
type webhookAdminResponder (line 26) | type webhookAdminResponder struct
method CreateProvisionerWebhook (line 66) | func (war *webhookAdminResponder) CreateProvisionerWebhook(w http.Resp...
method DeleteProvisionerWebhook (line 131) | func (war *webhookAdminResponder) DeleteProvisionerWebhook(w http.Resp...
method UpdateProvisionerWebhook (line 165) | func (war *webhookAdminResponder) UpdateProvisionerWebhook(w http.Resp...
function NewWebhookAdminResponder (line 29) | func NewWebhookAdminResponder() WebhookAdminResponder {
function validateWebhook (line 33) | func validateWebhook(webhook *linkedca.Webhook) error {
FILE: authority/admin/api/webhook_test.go
function assertEqualWebhook (line 23) | func assertEqualWebhook(t *testing.T, a, b *linkedca.Webhook) {
function TestWebhookAdminResponder_CreateProvisionerWebhook (line 33) | func TestWebhookAdminResponder_CreateProvisionerWebhook(t *testing.T) {
function TestWebhookAdminResponder_DeleteProvisionerWebhook (line 310) | func TestWebhookAdminResponder_DeleteProvisionerWebhook(t *testing.T) {
function TestWebhookAdminResponder_UpdateProvisionerWebhook (line 427) | func TestWebhookAdminResponder_UpdateProvisionerWebhook(t *testing.T) {
FILE: authority/admin/db.go
constant DefaultAuthorityID (line 16) | DefaultAuthorityID = "00000000-0000-0000-0000-000000000000"
function UnmarshalProvisionerDetails (line 24) | func UnmarshalProvisionerDetails(typ linkedca.Provisioner_Type, data []b...
type DB (line 60) | type DB interface
type dbKey (line 79) | type dbKey struct
function NewContext (line 82) | func NewContext(ctx context.Context, db DB) context.Context {
function FromContext (line 87) | func FromContext(ctx context.Context) (db DB, ok bool) {
function MustFromContext (line 94) | func MustFromContext(ctx context.Context) DB {
type MockDB (line 107) | type MockDB struct
method CreateProvisioner (line 130) | func (m *MockDB) CreateProvisioner(ctx context.Context, prov *linkedca...
method GetProvisioner (line 140) | func (m *MockDB) GetProvisioner(ctx context.Context, id string) (*link...
method GetProvisioners (line 150) | func (m *MockDB) GetProvisioners(ctx context.Context) ([]*linkedca.Pro...
method UpdateProvisioner (line 160) | func (m *MockDB) UpdateProvisioner(ctx context.Context, prov *linkedca...
method DeleteProvisioner (line 168) | func (m *MockDB) DeleteProvisioner(ctx context.Context, id string) err...
method CreateAdmin (line 176) | func (m *MockDB) CreateAdmin(ctx context.Context, admin *linkedca.Admi...
method GetAdmin (line 184) | func (m *MockDB) GetAdmin(ctx context.Context, id string) (*linkedca.A...
method GetAdmins (line 194) | func (m *MockDB) GetAdmins(ctx context.Context) ([]*linkedca.Admin, er...
method UpdateAdmin (line 204) | func (m *MockDB) UpdateAdmin(ctx context.Context, adm *linkedca.Admin)...
method DeleteAdmin (line 212) | func (m *MockDB) DeleteAdmin(ctx context.Context, id string) error {
method CreateAuthorityPolicy (line 220) | func (m *MockDB) CreateAuthorityPolicy(ctx context.Context, policy *li...
method GetAuthorityPolicy (line 228) | func (m *MockDB) GetAuthorityPolicy(ctx context.Context) (*linkedca.Po...
method UpdateAuthorityPolicy (line 236) | func (m *MockDB) UpdateAuthorityPolicy(ctx context.Context, policy *li...
method DeleteAuthorityPolicy (line 244) | func (m *MockDB) DeleteAuthorityPolicy(ctx context.Context) error {
FILE: authority/admin/db/nosql/admin.go
type dbAdmin (line 16) | type dbAdmin struct
method convert (line 26) | func (dba *dbAdmin) convert() *linkedca.Admin {
method clone (line 38) | func (dba *dbAdmin) clone() *dbAdmin {
method getDBAdminBytes (line 43) | func (db *DB) getDBAdminBytes(_ context.Context, id string) ([]byte, err...
method unmarshalDBAdmin (line 53) | func (db *DB) unmarshalDBAdmin(data []byte, id string) (*dbAdmin, error) {
method getDBAdmin (line 68) | func (db *DB) getDBAdmin(ctx context.Context, id string) (*dbAdmin, erro...
method unmarshalAdmin (line 80) | func (db *DB) unmarshalAdmin(data []byte, id string) (*linkedca.Admin, e...
method GetAdmin (line 89) | func (db *DB) GetAdmin(ctx context.Context, id string) (*linkedca.Admin,...
method GetAdmins (line 105) | func (db *DB) GetAdmins(context.Context) ([]*linkedca.Admin, error) {
method CreateAdmin (line 132) | func (db *DB) CreateAdmin(ctx context.Context, adm *linkedca.Admin) error {
method UpdateAdmin (line 153) | func (db *DB) UpdateAdmin(ctx context.Context, adm *linkedca.Admin) error {
method DeleteAdmin (line 166) | func (db *DB) DeleteAdmin(ctx context.Context, id string) error {
FILE: authority/admin/db/nosql/admin_test.go
function TestDB_getDBAdminBytes (line 19) | func TestDB_getDBAdminBytes(t *testing.T) {
function TestDB_getDBAdmin (line 92) | func TestDB_getDBAdmin(t *testing.T) {
function TestDB_unmarshalDBAdmin (line 222) | func TestDB_unmarshalDBAdmin(t *testing.T) {
function TestDB_unmarshalAdmin (line 310) | func TestDB_unmarshalAdmin(t *testing.T) {
function TestDB_GetAdmin (line 385) | func TestDB_GetAdmin(t *testing.T) {
function TestDB_DeleteAdmin (line 539) | func TestDB_DeleteAdmin(t *testing.T) {
function TestDB_UpdateAdmin (line 683) | func TestDB_UpdateAdmin(t *testing.T) {
function TestDB_CreateAdmin (line 834) | func TestDB_CreateAdmin(t *testing.T) {
function TestDB_GetAdmins (line 932) | func TestDB_GetAdmins(t *testing.T) {
FILE: authority/admin/db/nosql/nosql.go
type DB (line 20) | type DB struct
method save (line 39) | func (db *DB) save(_ context.Context, id string, nu, old interface{}, ...
function New (line 26) | func New(db nosqlDB.DB, authorityID string) (*DB, error) {
function randID (line 73) | func randID() (val string, err error) {
type Clock (line 82) | type Clock struct
method Now (line 85) | func (c *Clock) Now() time.Time {
FILE: authority/admin/db/nosql/policy.go
type dbX509Policy (line 14) | type dbX509Policy struct
type dbX509Names (line 20) | type dbX509Names struct
type dbSSHPolicy (line 28) | type dbSSHPolicy struct
type dbSSHHostPolicy (line 35) | type dbSSHHostPolicy struct
type dbSSHHostNames (line 40) | type dbSSHHostNames struct
type dbSSHUserPolicy (line 46) | type dbSSHUserPolicy struct
type dbSSHUserNames (line 51) | type dbSSHUserNames struct
type dbPolicy (line 56) | type dbPolicy struct
type dbAuthorityPolicy (line 61) | type dbAuthorityPolicy struct
method convert (line 67) | func (dbap *dbAuthorityPolicy) convert() *linkedca.Policy {
method getDBAuthorityPolicyBytes (line 74) | func (db *DB) getDBAuthorityPolicyBytes(_ context.Context, authorityID s...
method unmarshalDBAuthorityPolicy (line 84) | func (db *DB) unmarshalDBAuthorityPolicy(data []byte) (*dbAuthorityPolic...
method getDBAuthorityPolicy (line 96) | func (db *DB) getDBAuthorityPolicy(ctx context.Context, authorityID stri...
method CreateAuthorityPolicy (line 116) | func (db *DB) CreateAuthorityPolicy(ctx context.Context, policy *linkedc...
method GetAuthorityPolicy (line 130) | func (db *DB) GetAuthorityPolicy(ctx context.Context) (*linkedca.Policy,...
method UpdateAuthorityPolicy (line 139) | func (db *DB) UpdateAuthorityPolicy(ctx context.Context, policy *linkedc...
method DeleteAuthorityPolicy (line 158) | func (db *DB) DeleteAuthorityPolicy(ctx context.Context) error {
function dbToLinked (line 171) | func dbToLinked(p *dbPolicy) *linkedca.Policy {
function linkedToDB (line 231) | func linkedToDB(p *linkedca.Policy) *dbPolicy {
FILE: authority/admin/db/nosql/policy_test.go
function TestDB_getDBAuthorityPolicyBytes (line 18) | func TestDB_getDBAuthorityPolicyBytes(t *testing.T) {
function TestDB_getDBAuthorityPolicy (line 96) | func TestDB_getDBAuthorityPolicy(t *testing.T) {
function TestDB_CreateAuthorityPolicy (line 236) | func TestDB_CreateAuthorityPolicy(t *testing.T) {
function TestDB_GetAuthorityPolicy (line 331) | func TestDB_GetAuthorityPolicy(t *testing.T) {
function TestDB_UpdateAuthorityPolicy (line 432) | func TestDB_UpdateAuthorityPolicy(t *testing.T) {
function TestDB_DeleteAuthorityPolicy (line 601) | func TestDB_DeleteAuthorityPolicy(t *testing.T) {
function Test_linkedToDB (line 741) | func Test_linkedToDB(t *testing.T) {
function Test_dbToLinked (line 978) | func Test_dbToLinked(t *testing.T) {
FILE: authority/admin/db/nosql/provisioner.go
type dbProvisioner (line 16) | type dbProvisioner struct
method clone (line 47) | func (dbp *dbProvisioner) clone() *dbProvisioner {
method convert2linkedca (line 52) | func (dbp *dbProvisioner) convert2linkedca() (*linkedca.Provisioner, e...
type dbBasicAuth (line 30) | type dbBasicAuth struct
type dbWebhook (line 35) | type dbWebhook struct
method getDBProvisionerBytes (line 73) | func (db *DB) getDBProvisionerBytes(_ context.Context, id string) ([]byt...
method unmarshalDBProvisioner (line 83) | func (db *DB) unmarshalDBProvisioner(data []byte, id string) (*dbProvisi...
method getDBProvisioner (line 98) | func (db *DB) getDBProvisioner(ctx context.Context, id string) (*dbProvi...
method unmarshalProvisioner (line 110) | func (db *DB) unmarshalProvisioner(data []byte, id string) (*linkedca.Pr...
method GetProvisioner (line 120) | func (db *DB) GetProvisioner(ctx context.Context, id string) (*linkedca....
method GetProvisioners (line 135) | func (db *DB) GetProvisioners(_ context.Context) ([]*linkedca.Provisione...
method CreateProvisioner (line 162) | func (db *DB) CreateProvisioner(ctx context.Context, prov *linkedca.Prov...
method UpdateProvisioner (line 195) | func (db *DB) UpdateProvisioner(ctx context.Context, prov *linkedca.Prov...
method DeleteProvisioner (line 220) | func (db *DB) DeleteProvisioner(ctx context.Context, id string) error {
function dbWebhooksToLinkedca (line 232) | func dbWebhooksToLinkedca(dbwhs []dbWebhook) []*linkedca.Webhook {
function linkedcaWebhooksToDB (line 268) | func linkedcaWebhooksToDB(lwhs []*linkedca.Webhook) []dbWebhook {
FILE: authority/admin/db/nosql/provisioner_test.go
function TestDB_getDBProvisionerBytes (line 18) | func TestDB_getDBProvisionerBytes(t *testing.T) {
function TestDB_getDBProvisioner (line 91) | func TestDB_getDBProvisioner(t *testing.T) {
function TestDB_unmarshalDBProvisioner (line 220) | func TestDB_unmarshalDBProvisioner(t *testing.T) {
function defaultDBP (line 311) | func defaultDBP(t *testing.T) *dbProvisioner {
function TestDB_unmarshalProvisioner (line 371) | func TestDB_unmarshalProvisioner(t *testing.T) {
function TestDB_GetProvisioner (line 444) | func TestDB_GetProvisioner(t *testing.T) {
function TestDB_DeleteProvisioner (line 583) | func TestDB_DeleteProvisioner(t *testing.T) {
function TestDB_GetProvisioners (line 721) | func TestDB_GetProvisioners(t *testing.T) {
function TestDB_CreateProvisioner (line 886) | func TestDB_CreateProvisioner(t *testing.T) {
function TestDB_UpdateProvisioner (line 994) | func TestDB_UpdateProvisioner(t *testing.T) {
function Test_linkedcaWebhooksToDB (line 1238) | func Test_linkedcaWebhooksToDB(t *testing.T) {
function Test_dbWebhooksToLinkedca (line 1318) | func Test_dbWebhooksToLinkedca(t *testing.T) {
FILE: authority/admin/errors.go
type ProblemType (line 13) | type ProblemType
method String (line 37) | func (ap ProblemType) String() string {
constant ErrorNotFoundType (line 17) | ErrorNotFoundType ProblemType = iota
constant ErrorAuthorityMismatchType (line 20) | ErrorAuthorityMismatchType
constant ErrorDeletedType (line 22) | ErrorDeletedType
constant ErrorBadRequestType (line 24) | ErrorBadRequestType
constant ErrorNotImplementedType (line 26) | ErrorNotImplementedType
constant ErrorUnauthorizedType (line 28) | ErrorUnauthorizedType
constant ErrorServerInternalType (line 30) | ErrorServerInternalType
constant ErrorConflictType (line 32) | ErrorConflictType
type errorMetadata (line 60) | type errorMetadata struct
type Error (line 114) | type Error struct
method IsType (line 123) | func (e *Error) IsType(pt ProblemType) bool {
method StatusCode (line 181) | func (e *Error) StatusCode() int {
method Error (line 186) | func (e *Error) Error() string {
method Cause (line 191) | func (e *Error) Cause() error {
method ToLog (line 199) | func (e *Error) ToLog() (interface{}, error) {
method Render (line 208) | func (e *Error) Render(w http.ResponseWriter, r *http.Request) {
function NewError (line 128) | func NewError(pt ProblemType, msg string, args ...interface{}) *Error {
function newError (line 132) | func newError(pt ProblemType, err error) *Error {
function NewErrorISE (line 153) | func NewErrorISE(msg string, args ...interface{}) *Error {
function WrapError (line 158) | func WrapError(typ ProblemType, err error, msg string, args ...interface...
function WrapErrorISE (line 176) | func WrapErrorISE(err error, msg string, args ...interface{}) *Error {
FILE: authority/administrator/collection.go
constant DefaultAdminLimit (line 14) | DefaultAdminLimit = 20
constant DefaultAdminMax (line 17) | DefaultAdminMax = 100
type adminSlice (line 19) | type adminSlice
method Len (line 21) | func (p adminSlice) Len() int { return len(p) }
method Less (line 22) | func (p adminSlice) Less(i, j int) bool { return p[i].Id < p[j].Id }
method Swap (line 23) | func (p adminSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
type Collection (line 26) | type Collection struct
method LoadByID (line 49) | func (c *Collection) LoadByID(id string) (*linkedca.Admin, bool) {
method LoadBySubProv (line 63) | func (c *Collection) LoadBySubProv(sub, provName string) (*linkedca.Ad...
method LoadByProvisioner (line 68) | func (c *Collection) LoadByProvisioner(provName string) ([]*linkedca.A...
method Store (line 82) | func (c *Collection) Store(adm *linkedca.Admin, prov provisioner.Inter...
method Remove (line 123) | func (c *Collection) Remove(id string) error {
method Update (line 181) | func (c *Collection) Update(id string, nu *linkedca.Admin) (*linkedca....
method SuperCount (line 198) | func (c *Collection) SuperCount() int {
method SuperCountByProvisioner (line 203) | func (c *Collection) SuperCountByProvisioner(provName string) int {
method Find (line 211) | func (c *Collection) Find(cursor string, limit int) ([]*linkedca.Admin...
function NewCollection (line 38) | func NewCollection(provisioners *provisioner.Collection) *Collection {
type subProv (line 53) | type subProv struct
function newSubProv (line 58) | func newSubProv(subject, prov string) subProv {
function loadAdmin (line 233) | func loadAdmin(m *sync.Map, key interface{}) (*linkedca.Admin, bool) {
FILE: authority/admins.go
method LoadAdminByID (line 12) | func (a *Authority) LoadAdminByID(id string) (*linkedca.Admin, bool) {
method LoadAdminBySubProv (line 19) | func (a *Authority) LoadAdminBySubProv(subject, prov string) (*linkedca....
method GetAdmins (line 27) | func (a *Authority) GetAdmins(cursor string, limit int) ([]*linkedca.Adm...
method StoreAdmin (line 35) | func (a *Authority) StoreAdmin(ctx context.Context, adm *linkedca.Admin,...
method UpdateAdmin (line 61) | func (a *Authority) UpdateAdmin(ctx context.Context, id string, nu *link...
method RemoveAdmin (line 78) | func (a *Authority) RemoveAdmin(ctx context.Context, id string) error {
method removeAdmin (line 86) | func (a *Authority) removeAdmin(ctx context.Context, id string) error {
FILE: authority/authority.go
type Authority (line 43) | type Authority struct
method ReloadAdminResources (line 242) | func (a *Authority) ReloadAdminResources(ctx context.Context) error {
method init (line 323) | func (a *Authority) init() error {
method initLogf (line 872) | func (a *Authority) initLogf(format string, v ...any) {
method GetID (line 879) | func (a *Authority) GetID() string {
method GetDatabase (line 889) | func (a *Authority) GetDatabase() db.AuthDB {
method GetAdminDatabase (line 894) | func (a *Authority) GetAdminDatabase() admin.DB {
method GetConfig (line 899) | func (a *Authority) GetConfig() *config.Config {
method GetBackdate (line 906) | func (a *Authority) GetBackdate() *time.Duration {
method GetInfo (line 915) | func (a *Authority) GetInfo() Info {
method IsAdminAPIEnabled (line 932) | func (a *Authority) IsAdminAPIEnabled() bool {
method Shutdown (line 937) | func (a *Authority) Shutdown() error {
method CloseForReload (line 950) | func (a *Authority) CloseForReload() {
method IsRevoked (line 966) | func (a *Authority) IsRevoked(sn string) (bool, error) {
method requiresSCEP (line 979) | func (a *Authority) requiresSCEP() bool {
method getSCEPProvisionerNames (line 990) | func (a *Authority) getSCEPProvisionerNames() (names []string) {
method GetSCEP (line 1001) | func (a *Authority) GetSCEP() *scep.Authority {
method HasACMEProvisioner (line 1006) | func (a *Authority) HasACMEProvisioner() bool {
method startCRLGenerator (line 1015) | func (a *Authority) startCRLGenerator() error {
type Info (line 117) | type Info struct
function New (line 126) | func New(cfg *config.Config, opts ...Option) (*Authority, error) {
function NewEmbedded (line 167) | func NewEmbedded(opts ...Option) (*Authority, error) {
type authorityKey (line 215) | type authorityKey struct
function NewContext (line 218) | func NewContext(ctx context.Context, a *Authority) context.Context {
function FromContext (line 223) | func FromContext(ctx context.Context) (a *Authority, ok bool) {
function MustFromContext (line 230) | func MustFromContext(ctx context.Context) *Authority {
FILE: authority/authority_test.go
function TestMain (line 29) | func TestMain(m *testing.M) {
function testAuthority (line 39) | func testAuthority(t *testing.T, opts ...Option) *Authority {
function TestAuthorityNew (line 121) | func TestAuthorityNew(t *testing.T) {
function TestAuthorityNew_bundles (line 203) | func TestAuthorityNew_bundles(t *testing.T) {
function TestAuthority_GetDatabase (line 327) | func TestAuthority_GetDatabase(t *testing.T) {
function TestNewEmbedded (line 349) | func TestNewEmbedded(t *testing.T) {
function TestNewEmbedded_Sign (line 422) | func TestNewEmbedded_Sign(t *testing.T) {
function TestNewEmbedded_GetTLSCertificate (line 448) | func TestNewEmbedded_GetTLSCertificate(t *testing.T) {
function TestAuthority_CloseForReload (line 468) | func TestAuthority_CloseForReload(t *testing.T) {
function testScepAuthority (line 482) | func testScepAuthority(t *testing.T, opts ...Option) *Authority {
function TestAuthority_GetSCEP (line 506) | func TestAuthority_GetSCEP(t *testing.T) {
function TestAuthority_GetID (line 578) | func TestAuthority_GetID(t *testing.T) {
FILE: authority/authorize.go
type Claims (line 25) | type Claims struct
type skipTokenReuseKey (line 32) | type skipTokenReuseKey struct
function NewContextWithSkipTokenReuse (line 36) | func NewContextWithSkipTokenReuse(ctx context.Context) context.Context {
function SkipTokenReuseFromContext (line 41) | func SkipTokenReuseFromContext(ctx context.Context) bool {
method getProvisionerFromToken (line 48) | func (a *Authority) getProvisionerFromToken(token string) (provisioner.I...
method authorizeToken (line 78) | func (a *Authority) authorizeToken(ctx context.Context, token string) (p...
method AuthorizeAdminToken (line 105) | func (a *Authority) AuthorizeAdminToken(r *http.Request, token string) (...
method UseToken (line 201) | func (a *Authority) UseToken(ctx context.Context, token string, prov pro...
method Authorize (line 230) | func (a *Authority) Authorize(ctx context.Context, token string) ([]prov...
method authorizeSign (line 266) | func (a *Authority) authorizeSign(ctx context.Context, token string) ([]...
method AuthorizeSign (line 282) | func (a *Authority) AuthorizeSign(token string) ([]provisioner.SignOptio...
method authorizeRevoke (line 290) | func (a *Authority) authorizeRevoke(ctx context.Context, token string) e...
method authorizeRenew (line 306) | func (a *Authority) authorizeRenew(ctx context.Context, cert *x509.Certi...
method authorizeSSHCertificate (line 335) | func (a *Authority) authorizeSSHCertificate(_ context.Context, cert *ssh...
method authorizeSSHSign (line 359) | func (a *Authority) authorizeSSHSign(ctx context.Context, token string) ...
method authorizeSSHRenew (line 373) | func (a *Authority) authorizeSSHRenew(ctx context.Context, token string)...
method authorizeSSHRekey (line 387) | func (a *Authority) authorizeSSHRekey(ctx context.Context, token string)...
method authorizeSSHRevoke (line 401) | func (a *Authority) authorizeSSHRevoke(ctx context.Context, token string...
method AuthorizeRenewToken (line 414) | func (a *Authority) AuthorizeRenewToken(ctx context.Context, ott string)...
function matchesAudience (line 468) | func matchesAudience(as, bs []string) bool {
function stripPort (line 485) | func stripPort(rawurl string) string {
FILE: authority/authorize_test.go
type tokOption (line 44) | type tokOption
function withSSHPOPFile (line 46) | func withSSHPOPFile(cert *ssh.Certificate) tokOption {
function generateToken (line 53) | func generateToken(sub, iss, aud string, sans []string, iat time.Time, j...
function generateCustomToken (line 92) | func generateCustomToken(sub, iss, aud string, jwk *jose.JSONWebKey, ext...
function TestAuthority_authorizeToken (line 125) | func TestAuthority_authorizeToken(t *testing.T) {
function TestAuthority_authorizeRevoke (line 401) | func TestAuthority_authorizeRevoke(t *testing.T) {
function TestAuthority_authorizeSign (line 485) | func TestAuthority_authorizeSign(t *testing.T) {
function TestAuthority_Authorize (line 572) | func TestAuthority_Authorize(t *testing.T) {
function TestAuthority_authorizeRenew (line 833) | func TestAuthority_authorizeRenew(t *testing.T) {
function generateSimpleSSHUserToken (line 969) | func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (...
type stepPayload (line 976) | type stepPayload struct
function generateSSHToken (line 980) | func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *prov...
function createSSHCert (line 1014) | func createSSHCert(cert *ssh.Certificate, signer ssh.Signer) (*ssh.Certi...
function TestAuthority_authorizeSSHSign (line 1036) | func TestAuthority_authorizeSSHSign(t *testing.T) {
function TestAuthority_authorizeSSHRenew (line 1115) | func TestAuthority_authorizeSSHRenew(t *testing.T) {
function TestAuthority_authorizeSSHRevoke (line 1232) | func TestAuthority_authorizeSSHRevoke(t *testing.T) {
function TestAuthority_authorizeSSHRekey (line 1330) | func TestAuthority_authorizeSSHRekey(t *testing.T) {
function TestAuthority_AuthorizeRenewToken (line 1426) | func TestAuthority_AuthorizeRenewToken(t *testing.T) {
FILE: authority/config/config.go
constant legacyAuthority (line 24) | legacyAuthority = "step-certificate-authority"
type Config (line 67) | type Config struct
method Init (line 242) | func (c *Config) Init() {
method Save (line 262) | func (c *Config) Save(filename string) error {
method Commit (line 280) | func (c *Config) Commit() error {
method WasLoadedFromFile (line 289) | func (c *Config) WasLoadedFromFile() bool {
method Filepath (line 295) | func (c *Config) Filepath() string {
method Validate (line 300) | func (c *Config) Validate() error {
method GetAudiences (line 386) | func (c *Config) GetAudiences() provisioner.Audiences {
method Audience (line 428) | func (c *Config) Audience(path string) []string {
type CRLConfig (line 94) | type CRLConfig struct
method IsEnabled (line 103) | func (c *CRLConfig) IsEnabled() bool {
method Validate (line 108) | func (c *CRLConfig) Validate() error {
method TickerDuration (line 131) | func (c *CRLConfig) TickerDuration() time.Duration {
type ASN1DN (line 145) | type ASN1DN struct
type AuthConfig (line 159) | type AuthConfig struct
method init (line 176) | func (c *AuthConfig) init() {
method Validate (line 191) | func (c *AuthConfig) Validate(provisioner.Audiences) error {
function LoadConfiguration (line 219) | func LoadConfiguration(filename string) (*Config, error) {
function toHostname (line 439) | func toHostname(name string) string {
FILE: authority/config/config_test.go
function TestConfigValidate (line 15) | func TestConfigValidate(t *testing.T) {
function TestAuthConfigValidate (line 228) | func TestAuthConfigValidate(t *testing.T) {
function Test_toHostname (line 309) | func Test_toHostname(t *testing.T) {
function TestConfig_Audience (line 329) | func TestConfig_Audience(t *testing.T) {
FILE: authority/config/ssh.go
type SSHConfig (line 11) | type SSHConfig struct
method Validate (line 45) | func (c *SSHConfig) Validate() error {
type Bastion (line 21) | type Bastion struct
type HostTag (line 31) | type HostTag struct
type Host (line 38) | type Host struct
type SSHPublicKey (line 59) | type SSHPublicKey struct
method Validate (line 67) | func (k *SSHPublicKey) Validate() error {
method PublicKey (line 86) | func (k *SSHPublicKey) PublicKey() ssh.PublicKey {
type SSHKeys (line 91) | type SSHKeys struct
FILE: authority/config/ssh_test.go
function TestSSHPublicKey_Validate (line 12) | func TestSSHPublicKey_Validate(t *testing.T) {
function TestSSHPublicKey_PublicKey (line 46) | func TestSSHPublicKey_PublicKey(t *testing.T) {
FILE: authority/config/tls_options.go
type TLSVersion (line 50) | type TLSVersion
method Validate (line 54) | func (v TLSVersion) Validate() error {
method Value (line 62) | func (v TLSVersion) Value() uint16 {
method String (line 67) | func (v TLSVersion) String() string {
type CipherSuites (line 96) | type CipherSuites
method Validate (line 100) | func (c CipherSuites) Validate() error {
method Value (line 110) | func (c CipherSuites) Value() []uint16 {
type TLSOptions (line 156) | type TLSOptions struct
method TLSConfig (line 164) | func (t *TLSOptions) TLSConfig() *tls.Config {
FILE: authority/config/tls_options_test.go
function TestTLSVersion_Validate (line 9) | func TestTLSVersion_Validate(t *testing.T) {
function TestTLSVersion_String (line 31) | func TestTLSVersion_String(t *testing.T) {
function TestCipherSuites_Validate (line 53) | func TestCipherSuites_Validate(t *testing.T) {
function TestCipherSuites_Value (line 92) | func TestCipherSuites_Value(t *testing.T) {
function TestTLSOptions_TLSConfig (line 131) | func TestTLSOptions_TLSConfig(t *testing.T) {
FILE: authority/config/types.go
type multiString (line 11) | type multiString
method First (line 15) | func (s multiString) First() string {
method HasEmpties (line 23) | func (s multiString) HasEmpties() bool {
method MarshalJSON (line 38) | func (s multiString) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 50) | func (s *multiString) UnmarshalJSON(data []byte) error {
FILE: authority/config/types_test.go
function Test_multiString_First (line 8) | func Test_multiString_First(t *testing.T) {
function Test_multiString_Empties (line 27) | func Test_multiString_Empties(t *testing.T) {
function Test_multiString_MarshalJSON (line 48) | func Test_multiString_MarshalJSON(t *testing.T) {
function Test_multiString_UnmarshalJSON (line 73) | func Test_multiString_UnmarshalJSON(t *testing.T) {
FILE: authority/export.go
method Export (line 24) | func (a *Authority) Export() (c *linkedca.Configuration, err error) {
function mustDuration (line 226) | func mustDuration(d *provisioner.Duration) string {
function mustMarshalToStruct (line 233) | func mustMarshalToStruct(v interface{}) *structpb.Struct {
function mustReadFileOrURI (line 245) | func mustReadFileOrURI(fn string, m map[string][]byte) string {
function mustReadFilesOrURIs (line 272) | func mustReadFilesOrURIs(fns []string, m map[string][]byte) []string {
function isFilename (line 280) | func isFilename(fn string) (bool, error) {
FILE: authority/http_client.go
function initializeSystemCertPool (line 20) | func initializeSystemCertPool() error {
function newHTTPClient (line 33) | func newHTTPClient(wt httptransport.Wrapper, roots ...*x509.Certificate)...
FILE: authority/http_client_test.go
function mustCertificate (line 23) | func mustCertificate(t *testing.T, a *Authority, csr *x509.CertificateRe...
function Test_newHTTPClient (line 60) | func Test_newHTTPClient(t *testing.T) {
FILE: authority/internal/constraints/constraints.go
type ConstraintError (line 15) | type ConstraintError struct
method Error (line 22) | func (e ConstraintError) Error() string {
method As (line 28) | func (e ConstraintError) As(v any) bool {
type Engine (line 42) | type Engine struct
method Validate (line 79) | func (e *Engine) Validate(dnsNames []string, ipAddresses []net.IP, ema...
method ValidateCertificate (line 133) | func (e *Engine) ValidateCertificate(cert *x509.Certificate) error {
function New (line 56) | func New(chain ...*x509.Certificate) *Engine {
FILE: authority/internal/constraints/constraints_test.go
function TestNew (line 13) | func TestNew(t *testing.T) {
function TestNew_hasNameConstraints (line 82) | func TestNew_hasNameConstraints(t *testing.T) {
function TestEngine_Validate (line 113) | func TestEngine_Validate(t *testing.T) {
function TestEngine_Validate_nil (line 257) | func TestEngine_Validate_nil(t *testing.T) {
function TestEngine_ValidateCertificate (line 264) | func TestEngine_ValidateCertificate(t *testing.T) {
FILE: authority/internal/constraints/verify.go
function checkNameConstraints (line 40) | func checkNameConstraints(nameType, name string, parsedName, permitted, ...
function matchDomainConstraint (line 92) | func matchDomainConstraint(domain, constraint string) (bool, error) {
function normalizeIP (line 134) | func normalizeIP(ip net.IP) net.IP {
function matchIPConstraint (line 141) | func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
function matchEmailConstraint (line 157) | func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bo...
function matchURIConstraint (line 173) | func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
function domainToReverseLabels (line 205) | func domainToReverseLabels(domain string) (reverseLabels []string, ok bo...
type rfc2821Mailbox (line 241) | type rfc2821Mailbox struct
function parseRFC2821Mailbox (line 249) | func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {
FILE: authority/linkedca.go
constant uuidPattern (line 34) | uuidPattern = "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]...
type linkedCaClient (line 36) | type linkedCaClient struct
method IsLinkedCA (line 129) | func (c *linkedCaClient) IsLinkedCA() bool {
method Run (line 133) | func (c *linkedCaClient) Run() {
method Stop (line 137) | func (c *linkedCaClient) Stop() {
method CreateProvisioner (line 141) | func (c *linkedCaClient) CreateProvisioner(ctx context.Context, prov *...
method GetProvisioner (line 158) | func (c *linkedCaClient) GetProvisioner(ctx context.Context, id string...
method GetProvisioners (line 168) | func (c *linkedCaClient) GetProvisioners(ctx context.Context) ([]*link...
method GetConfiguration (line 176) | func (c *linkedCaClient) GetConfiguration(ctx context.Context) (*linke...
method UpdateProvisioner (line 186) | func (c *linkedCaClient) UpdateProvisioner(ctx context.Context, prov *...
method DeleteProvisioner (line 198) | func (c *linkedCaClient) DeleteProvisioner(ctx context.Context, id str...
method CreateAdmin (line 205) | func (c *linkedCaClient) CreateAdmin(ctx context.Context, adm *linkedc...
method GetAdmin (line 219) | func (c *linkedCaClient) GetAdmin(ctx context.Context, id string) (*li...
method GetAdmins (line 229) | func (c *linkedCaClient) GetAdmins(ctx context.Context) ([]*linkedca.A...
method UpdateAdmin (line 237) | func (c *linkedCaClient) UpdateAdmin(ctx context.Context, adm *linkedc...
method DeleteAdmin (line 245) | func (c *linkedCaClient) DeleteAdmin(ctx context.Context, id string) e...
method GetCertificateData (line 252) | func (c *linkedCaClient) GetCertificateData(serial string) (*db.Certif...
method StoreCertificateChain (line 286) | func (c *linkedCaClient) StoreCertificateChain(p provisioner.Interface...
method StoreRenewedCertificate (line 301) | func (c *linkedCaClient) StoreRenewedCertificate(parent *x509.Certific...
method StoreSSHCertificate (line 312) | func (c *linkedCaClient) StoreSSHCertificate(p provisioner.Interface, ...
method StoreRenewedSSHCertificate (line 322) | func (c *linkedCaClient) StoreRenewedSSHCertificate(p provisioner.Inte...
method Revoke (line 333) | func (c *linkedCaClient) Revoke(crt *x509.Certificate, rci *db.Revoked...
method RevokeSSH (line 347) | func (c *linkedCaClient) RevokeSSH(cert *ssh.Certificate, rci *db.Revo...
method IsRevoked (line 361) | func (c *linkedCaClient) IsRevoked(serial string) (bool, error) {
method IsSSHRevoked (line 373) | func (c *linkedCaClient) IsSSHRevoked(serial string) (bool, error) {
method CreateAuthorityPolicy (line 385) | func (c *linkedCaClient) CreateAuthorityPolicy(_ context.Context, _ *l...
method GetAuthorityPolicy (line 389) | func (c *linkedCaClient) GetAuthorityPolicy(context.Context) (*linkedc...
method UpdateAuthorityPolicy (line 393) | func (c *linkedCaClient) UpdateAuthorityPolicy(_ context.Context, _ *l...
method DeleteAuthorityPolicy (line 397) | func (c *linkedCaClient) DeleteAuthorityPolicy(context.Context) error {
type linkedCAClaims (line 45) | type linkedCAClaims struct
function newLinkedCAClient (line 51) | func newLinkedCAClient(token string) (*linkedCaClient, error) {
function createProvisionerIdentity (line 401) | func createProvisionerIdentity(p provisioner.Interface) *linkedca.Provis...
function createRegistrationAuthorityProvisioner (line 412) | func createRegistrationAuthorityProvisioner(p provisioner.Interface) (*l...
function createAttestationData (line 429) | func createAttestationData(p provisioner.Interface) *linkedca.Attestatio...
function serializeCertificate (line 440) | func serializeCertificate(crt *x509.Certificate) string {
function serializeCertificateChain (line 450) | func serializeCertificateChain(fullchain ...*x509.Certificate) string {
function serializeSSHCertificate (line 461) | func serializeSSHCertificate(crt *ssh.Certificate) string {
function getAuthority (line 468) | func getAuthority(sans []string) (string, error) {
function getRootCertificate (line 481) | func getRootCertificate(endpoint, fingerprint string) (*x509.Certificate...
function login (line 531) | func login(authority, token string, csr *x509.CertificateRequest, signer...
FILE: authority/meter.go
type Meter (line 16) | type Meter interface
type noopMeter (line 52) | type noopMeter struct
method SSHRekeyed (line 54) | func (noopMeter) SSHRekeyed(*ssh.Certificate, provisioner.Interface, e...
method SSHRenewed (line 55) | func (noopMeter) SSHRenewed(*ssh.Certificate, provisioner.Interface, e...
method SSHSigned (line 56) | func (noopMeter) SSHSigned(*ssh.Certificate, provisioner.Interface, er...
method SSHWebhookAuthorized (line 57) | func (noopMeter) SSHWebhookAuthorized(provisioner.Interface, error) ...
method SSHWebhookEnriched (line 58) | func (noopMeter) SSHWebhookEnriched(provisioner.Interface, error) ...
method X509Rekeyed (line 59) | func (noopMeter) X509Rekeyed([]*x509.Certificate, provisioner.Interfac...
method X509Renewed (line 60) | func (noopMeter) X509Renewed([]*x509.Certificate, provisioner.Interfac...
method X509Signed (line 61) | func (noopMeter) X509Signed([]*x509.Certificate, provisioner.Interface...
method X509WebhookAuthorized (line 62) | func (noopMeter) X509WebhookAuthorized(provisioner.Interface, error) ...
method X509WebhookEnriched (line 63) | func (noopMeter) X509WebhookEnriched(provisioner.Interface, error) ...
method KMSSigned (line 64) | func (noopMeter) KMSSigned(error) ...
type instrumentedKeyManager (line 66) | type instrumentedKeyManager struct
method CreateSigner (line 87) | func (i *instrumentedKeyManager) CreateSigner(req *kmsapi.CreateSigner...
type instrumentedKeyAndDecrypterManager (line 71) | type instrumentedKeyAndDecrypterManager struct
method CreateDecrypter (line 95) | func (i *instrumentedKeyAndDecrypterManager) CreateDecrypter(req *kmsa...
function newInstrumentedKeyManager (line 77) | func newInstrumentedKeyManager(k kms.KeyManager, m Meter) kms.KeyManager {
type instrumentedKMSSigner (line 99) | type instrumentedKMSSigner struct
method Sign (line 104) | func (i *instrumentedKMSSigner) Sign(rand io.Reader, digest []byte, op...
FILE: authority/options.go
type Option (line 25) | type Option
function WithConfig (line 29) | func WithConfig(cfg *config.Config) Option {
function WithConfigFile (line 38) | func WithConfigFile(filename string) Option {
function WithPassword (line 47) | func WithPassword(password []byte) Option {
function WithSSHHostPassword (line 56) | func WithSSHHostPassword(password []byte) Option {
function WithSSHUserPassword (line 65) | func WithSSHUserPassword(password []byte) Option {
function WithIssuerPassword (line 74) | func WithIssuerPassword(password []byte) Option {
function WithDatabase (line 83) | func WithDatabase(d db.AuthDB) Option {
function WithQuietInit (line 91) | func WithQuietInit() Option {
function WithWebhookClient (line 99) | func WithWebhookClient(c provisioner.HTTPClient) Option {
function WithTransportWrapper (line 111) | func WithTransportWrapper(tw httptransport.Wrapper) Option {
function WithGetIdentityFunc (line 124) | func WithGetIdentityFunc(fn func(ctx context.Context, p provisioner.Inte...
function WithAuthorizeRenewFunc (line 133) | func WithAuthorizeRenewFunc(fn func(ctx context.Context, p *provisioner....
function WithAuthorizeSSHRenewFunc (line 142) | func WithAuthorizeSSHRenewFunc(fn func(ctx context.Context, p *provision...
function WithSSHBastionFunc (line 151) | func WithSSHBastionFunc(fn func(ctx context.Context, user, host string) ...
function WithSSHGetHosts (line 160) | func WithSSHGetHosts(fn func(ctx context.Context, cert *x509.Certificate...
function WithSSHCheckHost (line 170) | func WithSSHCheckHost(fn func(ctx context.Context, principal string, tok...
function WithKeyManager (line 179) | func WithKeyManager(k kms.KeyManager) Option {
function WithX509CAService (line 188) | func WithX509CAService(svc casapi.CertificateAuthorityService) Option {
function WithX509Signer (line 196) | func WithX509Signer(crt *x509.Certificate, s crypto.Signer) Option {
function WithX509SignerChain (line 202) | func WithX509SignerChain(issuerChain []*x509.Certificate, s crypto.Signe...
function WithX509SignerFunc (line 220) | func WithX509SignerFunc(fn func() ([]*x509.Certificate, crypto.Signer, e...
function WithFullSCEPOptions (line 237) | func WithFullSCEPOptions(options *scep.Options) Option {
function WithSCEPKeyManager (line 248) | func WithSCEPKeyManager(skm provisioner.SCEPKeyManager) Option {
function WithSSHUserSigner (line 256) | func WithSSHUserSigner(s crypto.Signer) Option {
function WithSSHHostSigner (line 272) | func WithSSHHostSigner(s crypto.Signer) Option {
function WithX509RootCerts (line 290) | func WithX509RootCerts(rootCerts ...*x509.Certificate) Option {
function WithX509FederatedCerts (line 300) | func WithX509FederatedCerts(certs ...*x509.Certificate) Option {
function WithX509IntermediateCerts (line 319) | func WithX509IntermediateCerts(intermediateCerts ...*x509.Certificate) O...
function WithX509RootBundle (line 328) | func WithX509RootBundle(pemCerts []byte) Option {
function WithX509FederatedBundle (line 342) | func WithX509FederatedBundle(pemCerts []byte) Option {
function WithAdminDB (line 354) | func WithAdminDB(d admin.DB) Option {
function WithProvisioners (line 364) | func WithProvisioners(ps *provisioner.Collection) Option {
function WithLinkedCAToken (line 373) | func WithLinkedCAToken(token string) Option {
function WithX509Enforcers (line 382) | func WithX509Enforcers(ces ...provisioner.CertificateEnforcer) Option {
function WithSkipInit (line 391) | func WithSkipInit() Option {
function readCertificateBundle (line 398) | func readCertificateBundle(pemCerts []byte) ([]*x509.Certificate, error) {
function WithMeter (line 421) | func WithMeter(m Meter) Option {
FILE: authority/policy.go
type policyErrorType (line 15) | type policyErrorType
constant AdminLockOut (line 18) | AdminLockOut policyErrorType = iota + 1
constant StoreFailure (line 19) | StoreFailure
constant ReloadFailure (line 20) | ReloadFailure
constant ConfigurationFailure (line 21) | ConfigurationFailure
constant EvaluationFailure (line 22) | EvaluationFailure
constant InternalFailure (line 23) | InternalFailure
type PolicyError (line 26) | type PolicyError struct
method Error (line 31) | func (p *PolicyError) Error() string {
method GetAuthorityPolicy (line 35) | func (a *Authority) GetAuthorityPolicy(ctx context.Context) (*linkedca.P...
method CreateAuthorityPolicy (line 50) | func (a *Authority) CreateAuthorityPolicy(ctx context.Context, adm *link...
method UpdateAuthorityPolicy (line 75) | func (a *Authority) UpdateAuthorityPolicy(ctx context.Context, adm *link...
method RemoveAuthorityPolicy (line 100) | func (a *Authority) RemoveAuthorityPolicy(ctx context.Context) error {
method checkAuthorityPolicy (line 121) | func (a *Authority) checkAuthorityPolicy(ctx context.Context, currentAdm...
method checkProvisionerPolicy (line 139) | func (a *Authority) checkProvisionerPolicy(ctx context.Context, provName...
method checkPolicy (line 157) | func (a *Authority) checkPolicy(_ context.Context, currentAdmin *linkedc...
method reloadPolicyEngines (line 209) | func (a *Authority) reloadPolicyEngines(ctx context.Context) error {
function isAllowed (line 244) | func isAllowed(engine authPolicy.X509Policy, sans []string) error {
FILE: authority/policy/engine.go
type Engine (line 12) | type Engine struct
method IsX509CertificateAllowed (line 58) | func (e *Engine) IsX509CertificateAllowed(cert *x509.Certificate) error {
method AreSANsAllowed (line 70) | func (e *Engine) AreSANsAllowed(sans []string) error {
method IsSSHCertificateAllowed (line 83) | func (e *Engine) IsSSHCertificateAllowed(cert *ssh.Certificate) error {
function New (line 19) | func New(options *Options) (*Engine, error) {
FILE: authority/policy/options.go
type Options (line 5) | type Options struct
method GetX509Options (line 12) | func (o *Options) GetX509Options() *X509PolicyOptions {
method GetSSHOptions (line 21) | func (o *Options) GetSSHOptions() *SSHPolicyOptions {
type X509PolicyOptionsInterface (line 30) | type X509PolicyOptionsInterface interface
type X509PolicyOptions (line 38) | type X509PolicyOptions struct
method GetAllowedNameOptions (line 70) | func (o *X509PolicyOptions) GetAllowedNameOptions() *X509NameOptions {
method GetDeniedNameOptions (line 78) | func (o *X509PolicyOptions) GetDeniedNameOptions() *X509NameOptions {
method AreWildcardNamesAllowed (line 87) | func (o *X509PolicyOptions) AreWildcardNamesAllowed() bool {
type X509NameOptions (line 51) | type X509NameOptions struct
method HasNames (line 61) | func (o *X509NameOptions) HasNames() bool {
type SSHPolicyOptionsInterface (line 96) | type SSHPolicyOptionsInterface interface
type SSHPolicyOptions (line 105) | type SSHPolicyOptions struct
method GetAllowedUserNameOptions (line 114) | func (o *SSHPolicyOptions) GetAllowedUserNameOptions() *SSHNameOptions {
method GetDeniedUserNameOptions (line 123) | func (o *SSHPolicyOptions) GetDeniedUserNameOptions() *SSHNameOptions {
method GetAllowedHostNameOptions (line 132) | func (o *SSHPolicyOptions) GetAllowedHostNameOptions() *SSHNameOptions {
method GetDeniedHostNameOptions (line 141) | func (o *SSHPolicyOptions) GetDeniedHostNameOptions() *SSHNameOptions {
type SSHUserCertificateOptions (line 149) | type SSHUserCertificateOptions struct
method GetAllowedNameOptions (line 171) | func (o *SSHUserCertificateOptions) GetAllowedNameOptions() *SSHNameOp...
method GetDeniedNameOptions (line 180) | func (o *SSHUserCertificateOptions) GetDeniedNameOptions() *SSHNameOpt...
type SSHHostCertificateOptions (line 159) | type SSHHostCertificateOptions
type SSHNameOptions (line 162) | type SSHNameOptions struct
method HasNames (line 189) | func (o *SSHNameOptions) HasNames() bool {
FILE: authority/policy/options_test.go
function TestX509PolicyOptions_IsWildcardLiteralAllowed (line 7) | func TestX509PolicyOptions_IsWildcardLiteralAllowed(t *testing.T) {
FILE: authority/policy/policy.go
type X509Policy (line 12) | type X509Policy
type UserPolicy (line 15) | type UserPolicy
type HostPolicy (line 18) | type HostPolicy
function NewX509PolicyEngine (line 21) | func NewX509PolicyEngine(policyOptions X509PolicyOptionsInterface) (X509...
type sshPolicyEngineType (line 69) | type sshPolicyEngineType
constant UserPolicyEngineType (line 72) | UserPolicyEngineType sshPolicyEngineType = "user"
constant HostPolicyEngineType (line 73) | HostPolicyEngineType sshPolicyEngineType = "host"
function NewSSHUserPolicyEngine (line 77) | func NewSSHUserPolicyEngine(policyOptions SSHPolicyOptionsInterface) (Us...
function NewSSHHostPolicyEngine (line 86) | func NewSSHHostPolicyEngine(policyOptions SSHPolicyOptionsInterface) (Ho...
function newSSHPolicyEngine (line 95) | func newSSHPolicyEngine(policyOptions SSHPolicyOptionsInterface, typ ssh...
function LinkedToCertificates (line 147) | func LinkedToCertificates(p *linkedca.Policy) *Options {
FILE: authority/policy/policy_test.go
function TestPolicyToCertificates (line 11) | func TestPolicyToCertificates(t *testing.T) {
FILE: authority/policy_test.go
function TestAuthority_checkPolicy (line 22) | func TestAuthority_checkPolicy(t *testing.T) {
function mustPolicyEngine (line 198) | func mustPolicyEngine(t *testing.T, options *policy.Options) *policy.Eng...
function TestAuthority_reloadPolicyEngines (line 206) | func TestAuthority_reloadPolicyEngines(t *testing.T) {
function TestAuthority_checkAuthorityPolicy (line 869) | func TestAuthority_checkAuthorityPolicy(t *testing.T) {
function TestAuthority_checkProvisionerPolicy (line 1005) | func TestAuthority_checkProvisionerPolicy(t *testing.T) {
function TestAuthority_RemoveAuthorityPolicy (line 1098) | func TestAuthority_RemoveAuthorityPolicy(t *testing.T) {
function TestAuthority_GetAuthorityPolicy (line 1193) | func TestAuthority_GetAuthorityPolicy(t *testing.T) {
function TestAuthority_CreateAuthorityPolicy (line 1268) | func TestAuthority_CreateAuthorityPolicy(t *testing.T) {
function TestAuthority_UpdateAuthorityPolicy (line 1448) | func TestAuthority_UpdateAuthorityPolicy(t *testing.T) {
FILE: authority/poolhttp/poolhttp.go
type Transporter (line 12) | type Transporter interface
type Client (line 19) | type Client struct
method SetNew (line 37) | func (c *Client) SetNew(fn func() *http.Client) {
method getClient (line 46) | func (c *Client) getClient() *http.Client {
method Get (line 58) | func (c *Client) Get(u string) (resp *http.Response, err error) {
method Do (line 71) | func (c *Client) Do(req *http.Request) (resp *http.Response, err error) {
method Transport (line 84) | func (c *Client) Transport() *http.Transport {
function New (line 26) | func New(fn func() *http.Client) *Client {
FILE: authority/poolhttp/poolhttp_test.go
function requireBody (line 15) | func requireBody(t *testing.T, want string, r io.ReadCloser) {
function TestClient (line 26) | func TestClient(t *testing.T) {
function TestClient_SetNew (line 69) | func TestClient_SetNew(t *testing.T) {
function TestClient_parallel (line 100) | func TestClient_parallel(t *testing.T) {
FILE: authority/provisioner/acme.go
type ACMEChallenge (line 18) | type ACMEChallenge
method String (line 37) | func (c ACMEChallenge) String() string {
method Validate (line 42) | func (c ACMEChallenge) Validate() error {
constant HTTP_01 (line 23) | HTTP_01 ACMEChallenge = "http-01"
constant DNS_01 (line 25) | DNS_01 ACMEChallenge = "dns-01"
constant TLS_ALPN_01 (line 27) | TLS_ALPN_01 ACMEChallenge = "tls-alpn-01"
constant DEVICE_ATTEST_01 (line 29) | DEVICE_ATTEST_01 ACMEChallenge = "device-attest-01"
constant WIREOIDC_01 (line 31) | WIREOIDC_01 ACMEChallenge = "wire-oidc-01"
constant WIREDPOP_01 (line 33) | WIREDPOP_01 ACMEChallenge = "wire-dpop-01"
type ACMEAttestationFormat (line 53) | type ACMEAttestationFormat
method String (line 70) | func (f ACMEAttestationFormat) String() string {
method Validate (line 75) | func (f ACMEAttestationFormat) Validate() error {
constant APPLE (line 57) | APPLE ACMEAttestationFormat = "apple"
constant STEP (line 63) | STEP ACMEAttestationFormat = "step"
constant TPM (line 66) | TPM ACMEAttestationFormat = "tpm"
type ACME (line 86) | type ACME struct
method GetID (line 128) | func (p ACME) GetID() string {
method GetIDForToken (line 137) | func (p *ACME) GetIDForToken() string {
method GetTokenID (line 143) | func (p *ACME) GetTokenID(string) (string, error) {
method GetName (line 148) | func (p *ACME) GetName() string {
method GetType (line 153) | func (p *ACME) GetType() Type {
method GetEncryptedKey (line 158) | func (p *ACME) GetEncryptedKey() (string, string, bool) {
method GetOptions (line 163) | func (p *ACME) GetOptions() *Options {
method DefaultTLSCertDuration (line 169) | func (p *ACME) DefaultTLSCertDuration() time.Duration {
method Init (line 174) | func (p *ACME) Init(config Config) (err error) {
method initializeWireOptions (line 227) | func (p *ACME) initializeWireOptions() error {
method AuthorizeOrderIdentifier (line 282) | func (p *ACME) AuthorizeOrderIdentifier(_ context.Context, identifier ...
method AuthorizeSign (line 319) | func (p *ACME) AuthorizeSign(context.Context, string) ([]SignOption, e...
method AuthorizeRevoke (line 340) | func (p *ACME) AuthorizeRevoke(context.Context, string) error {
method AuthorizeRenew (line 348) | func (p *ACME) AuthorizeRenew(ctx context.Context, cert *x509.Certific...
method IsChallengeEnabled (line 355) | func (p *ACME) IsChallengeEnabled(_ context.Context, challenge ACMECha...
method IsAttestationFormatEnabled (line 373) | func (p *ACME) IsAttestationFormatEnabled(_ context.Context, format AC...
method GetAttestationRoots (line 393) | func (p *ACME) GetAttestationRoots() (*x509.CertPool, bool) {
type ACMEIdentifierType (line 261) | type ACMEIdentifierType
constant IP (line 265) | IP ACMEIdentifierType = "ip"
constant DNS (line 267) | DNS ACMEIdentifierType = "dns"
constant WireUser (line 269) | WireUser ACMEIdentifierType = "wireapp-user"
constant WireDevice (line 271) | WireDevice ACMEIdentifierType = "wireapp-device"
type ACMEIdentifier (line 275) | type ACMEIdentifier struct
FILE: authority/provisioner/acme_118_test.go
function TestACME_GetAttestationRoots (line 12) | func TestACME_GetAttestationRoots(t *testing.T) {
FILE: authority/provisioner/acme_119_test.go
function TestACME_GetAttestationRoots (line 12) | func TestACME_GetAttestationRoots(t *testing.T) {
FILE: authority/provisioner/acme_test.go
function TestACMEChallenge_Validate (line 20) | func TestACMEChallenge_Validate(t *testing.T) {
function TestACMEAttestationFormat_Validate (line 48) | func TestACMEAttestationFormat_Validate(t *testing.T) {
function TestACME_Getters (line 73) | func TestACME_Getters(t *testing.T) {
function TestACME_Init (line 90) | func TestACME_Init(t *testing.T) {
function TestACME_AuthorizeRenew (line 250) | func TestACME_AuthorizeRenew(t *testing.T) {
function TestACME_AuthorizeSign (line 309) | func TestACME_AuthorizeSign(t *testing.T) {
function TestACME_IsChallengeEnabled (line 373) | func TestACME_IsChallengeEnabled(t *testing.T) {
function TestACME_IsAttestationFormatEnabled (line 417) | func TestACME_IsAttestationFormatEnabled(t *testing.T) {
FILE: authority/provisioner/aws.go
constant awsIssuer (line 33) | awsIssuer = "ec2.amazonaws.com"
constant awsIdentityURL (line 36) | awsIdentityURL = "http://169.254.169.254/latest/dynamic/instance-identit...
constant awsSignatureURL (line 39) | awsSignatureURL = "http://169.254.169.254/latest/dynamic/instance-identi...
constant awsAPITokenURL (line 42) | awsAPITokenURL = "http://169.254.169.254/latest/api/token"
constant awsAPITokenTTL (line 46) | awsAPITokenTTL = "30"
constant awsMetadataTokenHeader (line 49) | awsMetadataTokenHeader = "X-aws-ec2-metadata-token"
constant awsMetadataTokenTTLHeader (line 52) | awsMetadataTokenTTLHeader = "X-aws-ec2-metadata-token-ttl-seconds"
constant awsSignatureAlgorithm (line 62) | awsSignatureAlgorithm = x509.SHA256WithRSA
type awsConfig (line 64) | type awsConfig struct
function newAWSConfig (line 73) | func newAWSConfig(certPath string) (*awsConfig, error) {
type awsPayload (line 116) | type awsPayload struct
type awsAmazonPayload (line 123) | type awsAmazonPayload struct
type awsInstanceIdentityDocument (line 128) | type awsInstanceIdentityDocument struct
type AWS (line 163) | type AWS struct
method GetID (line 181) | func (p *AWS) GetID() string {
method GetIDForToken (line 190) | func (p *AWS) GetIDForToken() string {
method GetTokenID (line 195) | func (p *AWS) GetTokenID(token string) (string, error) {
method GetName (line 214) | func (p *AWS) GetName() string {
method GetType (line 219) | func (p *AWS) GetType() Type {
method GetEncryptedKey (line 224) | func (p *AWS) GetEncryptedKey() (kid, key string, ok bool) {
method GetIdentityToken (line 230) | func (p *AWS) GetIdentityToken(subject, caURL string) (string, error) {
method Init (line 302) | func (p *AWS) Init(config Config) (err error) {
method AuthorizeSign (line 339) | func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]Sign...
method AuthorizeRenew (line 401) | func (p *AWS) AuthorizeRenew(ctx context.Context, cert *x509.Certifica...
method assertConfig (line 406) | func (p *AWS) assertConfig() (err error) {
method checkSignature (line 415) | func (p *AWS) checkSignature(signed, signature []byte) error {
method readURL (line 427) | func (p *AWS) readURL(url string) ([]byte, error) {
method readURLv1 (line 465) | func (p *AWS) readURLv1(url string) (*http.Response, error) {
method readURLv2 (line 479) | func (p *AWS) readURLv2(url string) (*http.Response, error) {
method readResponseBody (line 514) | func (p *AWS) readResponseBody(resp *http.Response) ([]byte, error) {
method authorizeToken (line 526) | func (p *AWS) authorizeToken(token string) (*awsPayload, error) {
method AuthorizeSSHSign (line 616) | func (p *AWS) AuthorizeSSHSign(_ context.Context, token string) ([]Sig...
FILE: authority/provisioner/aws_test.go
function TestAWS_Getters (line 27) | func TestAWS_Getters(t *testing.T) {
function TestAWS_GetTokenID (line 47) | func TestAWS_GetTokenID(t *testing.T) {
function TestAWS_GetIdentityToken (line 98) | func TestAWS_GetIdentityToken(t *testing.T) {
function TestAWS_GetIdentityToken_V1Only (line 202) | func TestAWS_GetIdentityToken_V1Only(t *testing.T) {
function TestAWS_GetIdentityToken_BadIDMS (line 231) | func TestAWS_GetIdentityToken_BadIDMS(t *testing.T) {
function TestAWS_Init (line 249) | func TestAWS_Init(t *testing.T) {
function TestAWS_authorizeToken (line 312) | func TestAWS_authorizeToken(t *testing.T) {
function TestAWS_AuthorizeSign (line 545) | func TestAWS_AuthorizeSign(t *testing.T) {
function TestAWS_AuthorizeSSHSign (line 716) | func TestAWS_AuthorizeSSHSign(t *testing.T) {
function TestAWS_AuthorizeRenew (line 833) | func TestAWS_AuthorizeRenew(t *testing.T) {
function TestAWS_HardcodedCertificates (line 878) | func TestAWS_HardcodedCertificates(t *testing.T) {
FILE: authority/provisioner/azure.go
constant azureOIDCBaseURL (line 27) | azureOIDCBaseURL = "https://login.microsoftonline.com"
constant azureIdentityTokenURL (line 30) | azureIdentityTokenURL = "http://169.254.169.254/metadata/identity/oauth2...
constant azureIdentityTokenAPIVersion (line 32) | azureIdentityTokenAPIVersion = "2018-02-01"
constant azureInstanceComputeURL (line 35) | azureInstanceComputeURL = "http://169.254.169.254/metadata/instance/comp...
constant azureDefaultAudience (line 38) | azureDefaultAudience = "https://management.azure.com/"
type azureConfig (line 54) | type azureConfig struct
function newAzureConfig (line 60) | func newAzureConfig(tenantID string) *azureConfig {
type azureIdentityToken (line 68) | type azureIdentityToken struct
type azurePayload (line 80) | type azurePayload struct
type Azure (line 106) | type Azure struct
method GetID (line 128) | func (p *Azure) GetID() string {
method GetIDForToken (line 137) | func (p *Azure) GetIDForToken() string {
method GetTokenID (line 144) | func (p *Azure) GetTokenID(token string) (string, error) {
method GetName (line 169) | func (p *Azure) GetName() string {
method GetType (line 174) | func (p *Azure) GetType() Type {
method GetEncryptedKey (line 179) | func (p *Azure) GetEncryptedKey() (kid, key string, ok bool) {
method GetIdentityToken (line 185) | func (p *Azure) GetIdentityToken(subject, caURL string) (string, error) {
method Init (line 238) | func (p *Azure) Init(config Config) (err error) {
method authorizeToken (line 270) | func (p *Azure) authorizeToken(token string) (*azurePayload, string, s...
method AuthorizeSign (line 319) | func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]Si...
method AuthorizeRenew (line 419) | func (p *Azure) AuthorizeRenew(ctx context.Context, cert *x509.Certifi...
method AuthorizeSSHSign (line 424) | func (p *Azure) AuthorizeSSHSign(_ context.Context, token string) ([]S...
method assertConfig (line 490) | func (p *Azure) assertConfig() {
method getAzureEnvironment (line 497) | func (p *Azure) getAzureEnvironment() (string, error) {
FILE: authority/provisioner/azure_test.go
function TestAzure_Getters (line 25) | func TestAzure_Getters(t *testing.T) {
function TestAzure_GetTokenID (line 44) | func TestAzure_GetTokenID(t *testing.T) {
function TestAzure_GetIdentityToken (line 94) | func TestAzure_GetIdentityToken(t *testing.T) {
function TestAzure_Init (line 185) | func TestAzure_Init(t *testing.T) {
function TestAzure_authorizeToken (line 252) | func TestAzure_authorizeToken(t *testing.T) {
function TestAzure_AuthorizeSign (line 396) | func TestAzure_AuthorizeSign(t *testing.T) {
function TestAzure_AuthorizeRenew (line 581) | func TestAzure_AuthorizeRenew(t *testing.T) {
function TestAzure_AuthorizeSSHSign (line 626) | func TestAzure_AuthorizeSSHSign(t *testing.T) {
function TestAzure_assertConfig (line 735) | func TestAzure_assertConfig(t *testing.T) {
FILE: authority/provisioner/claims.go
type Claims (line 11) | type Claims struct
type Claimer (line 36) | type Claimer struct
method Claims (line 49) | func (c *Claimer) Claims() Claims {
method DefaultTLSCertDuration (line 75) | func (c *Claimer) DefaultTLSCertDuration() time.Duration {
method MinTLSCertDuration (line 85) | func (c *Claimer) MinTLSCertDuration() time.Duration {
method MaxTLSCertDuration (line 98) | func (c *Claimer) MaxTLSCertDuration() time.Duration {
method IsDisableRenewal (line 111) | func (c *Claimer) IsDisableRenewal() bool {
method IsDisableSmallstepExtensions (line 120) | func (c *Claimer) IsDisableSmallstepExtensions() bool {
method AllowRenewalAfterExpiry (line 130) | func (c *Claimer) AllowRenewalAfterExpiry() bool {
method DefaultSSHCertDuration (line 139) | func (c *Claimer) DefaultSSHCertDuration(certType uint32) (time.Durati...
method DefaultUserSSHCertDuration (line 155) | func (c *Claimer) DefaultUserSSHCertDuration() time.Duration {
method MinUserSSHCertDuration (line 165) | func (c *Claimer) MinUserSSHCertDuration() time.Duration {
method MaxUserSSHCertDuration (line 178) | func (c *Claimer) MaxUserSSHCertDuration() time.Duration {
method DefaultHostSSHCertDuration (line 191) | func (c *Claimer) DefaultHostSSHCertDuration() time.Duration {
method MinHostSSHCertDuration (line 201) | func (c *Claimer) MinHostSSHCertDuration() time.Duration {
method MaxHostSSHCertDuration (line 214) | func (c *Claimer) MaxHostSSHCertDuration() time.Duration {
method IsSSHCAEnabled (line 227) | func (c *Claimer) IsSSHCAEnabled() bool {
method Validate (line 235) | func (c *Claimer) Validate() error {
function NewClaimer (line 42) | func NewClaimer(claims *Claims, global Claims) (*Claimer, error) {
FILE: authority/provisioner/claims_test.go
function TestClaimer_DefaultSSHCertDuration (line 10) | func TestClaimer_DefaultSSHCertDuration(t *testing.T) {
FILE: authority/provisioner/collection.go
constant DefaultProvisionersLimit (line 22) | DefaultProvisionersLimit = 20
constant DefaultProvisionersMax (line 25) | DefaultProvisionersMax = 100
type uidProvisioner (line 27) | type uidProvisioner struct
type provisionerSlice (line 32) | type provisionerSlice
method Len (line 34) | func (p provisionerSlice) Len() int { return len(p) }
method Less (line 35) | func (p provisionerSlice) Less(i, j int) bool { return p[i].uid < p[j]...
method Swap (line 36) | func (p provisionerSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
type loadByTokenPayload (line 40) | type loadByTokenPayload struct
type Collection (line 48) | type Collection struct
method Load (line 70) | func (c *Collection) Load(id string) (Interface, bool) {
method LoadByName (line 75) | func (c *Collection) LoadByName(name string) (Interface, bool) {
method LoadByTokenID (line 82) | func (c *Collection) LoadByTokenID(tokenProvisionerID string) (Interfa...
method LoadByToken (line 87) | func (c *Collection) LoadByToken(token *jose.JSONWebToken, claims *jos...
method LoadByCertificate (line 155) | func (c *Collection) LoadByCertificate(cert *x509.Certificate) (Interf...
method LoadEncryptedKey (line 173) | func (c *Collection) LoadEncryptedKey(keyID string) (string, bool) {
method Store (line 184) | func (c *Collection) Store(p Interface) error {
method Remove (line 226) | func (c *Collection) Remove(id string) error {
method Update (line 259) | func (c *Collection) Update(nu Interface) error {
method Find (line 286) | func (c *Collection) Find(cursor string, limit int) (List, string) {
function NewCollection (line 59) | func NewCollection(audiences Audiences) *Collection {
function loadProvisioner (line 309) | func loadProvisioner(m *sync.Map, key string) (Interface, bool) {
function provisionerSum (line 323) | func provisionerSum(p Interface) []byte {
function matchesAudience (line 330) | func matchesAudience(as, bs []string) bool {
function stripPort (line 347) | func stripPort(rawurl string) string {
function extractFragment (line 357) | func extractFragment(audience []string) string {
FILE: authority/provisioner/collection_test.go
function TestCollection_Load (line 17) | func TestCollection_Load(t *testing.T) {
function TestCollection_LoadByTokenID (line 57) | func TestCollection_LoadByTokenID(t *testing.T) {
function TestCollection_LoadByToken (line 102) | func TestCollection_LoadByToken(t *testing.T) {
function TestCollection_LoadByCertificate (line 196) | func TestCollection_LoadByCertificate(t *testing.T) {
function TestCollection_LoadEncryptedKey (line 276) | func TestCollection_LoadEncryptedKey(t *testing.T) {
function TestCollection_Store (line 316) | func TestCollection_Store(t *testing.T) {
function TestCollection_Find (line 345) | func TestCollection_Find(t *testing.T) {
function Test_matchesAudience (line 392) | func Test_matchesAudience(t *testing.T) {
function Test_stripPort (line 446) | func Test_stripPort(t *testing.T) {
FILE: authority/provisioner/controller.go
type Controller (line 23) | type Controller struct
method GetHTTPClient (line 74) | func (c *Controller) GetHTTPClient() HTTPClient {
method GetIdentity (line 82) | func (c *Controller) GetIdentity(ctx context.Context, email string) (*...
method AuthorizeRenew (line 91) | func (c *Controller) AuthorizeRenew(ctx context.Context, cert *x509.Ce...
method AuthorizeSSHRenew (line 100) | func (c *Controller) AuthorizeSSHRenew(ctx context.Context, cert *ssh....
method newWebhookController (line 107) | func (c *Controller) newWebhookController(templateData WebhookSetter, ...
method getPolicy (line 251) | func (c *Controller) getPolicy() *policyEngine {
function NewController (line 38) | func NewController(p Interface, claims *Claims, config Config, options *...
type Identity (line 127) | type Identity struct
type GetIdentityFunc (line 133) | type GetIdentityFunc
type AuthorizeRenewFunc (line 137) | type AuthorizeRenewFunc
type AuthorizeSSHRenewFunc (line 141) | type AuthorizeSSHRenewFunc
function DefaultIdentityFunc (line 146) | func DefaultIdentityFunc(_ context.Context, p Interface, email string) (...
function DefaultAuthorizeRenew (line 173) | func DefaultAuthorizeRenew(_ context.Context, p *Controller, cert *x509....
function DefaultAuthorizeSSHRenew (line 195) | func DefaultAuthorizeSSHRenew(_ context.Context, p *Controller, cert *ss...
function SanitizeStringSlices (line 212) | func SanitizeStringSlices(original []string) []string {
function SanitizeSSHUserPrincipal (line 231) | func SanitizeSSHUserPrincipal(email string) string {
FILE: authority/provisioner/controller_test.go
function mustClaimer (line 24) | func mustClaimer(t *testing.T, claims *Claims, global Claims) *Claimer {
function mustDuration (line 32) | func mustDuration(t *testing.T, s string) *Duration {
function mustNewPolicyEngine (line 41) | func mustNewPolicyEngine(t *testing.T, options *Options) *policyEngine {
function TestNewController (line 50) | func TestNewController(t *testing.T) {
function TestController_GetHTTPClient (line 163) | func TestController_GetHTTPClient(t *testing.T) {
function TestController_GetIdentity (line 187) | func TestController_GetIdentity(t *testing.T) {
function TestController_AuthorizeRenew (line 241) | func TestController_AuthorizeRenew(t *testing.T) {
function TestController_AuthorizeSSHRenew (line 312) | func TestController_AuthorizeSSHRenew(t *testing.T) {
function TestDefaultAuthorizeRenew (line 383) | func TestDefaultAuthorizeRenew(t *testing.T) {
function TestDefaultAuthorizeSSHRenew (line 441) | func TestDefaultAuthorizeSSHRenew(t *testing.T) {
function Test_newWebhookController (line 499) | func Test_newWebhookController(t *testing.T) {
FILE: authority/provisioner/duration.go
type Duration (line 11) | type Duration struct
method MarshalJSON (line 30) | func (d *Duration) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 39) | func (d *Duration) UnmarshalJSON(data []byte) (err error) {
method Value (line 58) | func (d *Duration) Value() time.Duration {
function NewDuration (line 17) | func NewDuration(s string) (*Duration, error) {
FILE: authority/provisioner/duration_test.go
function TestNewDuration (line 9) | func TestNewDuration(t *testing.T) {
function TestDuration_UnmarshalJSON (line 38) | func TestDuration_UnmarshalJSON(t *testing.T) {
function TestDuration_MarshalJSON (line 69) | func TestDuration_MarshalJSON(t *testing.T) {
function TestDuration_Value (line 92) | func TestDuration_Value(t *testing.T) {
FILE: authority/provisioner/extension.go
type Extension (line 18) | type Extension struct
method Marshal (line 33) | func (e *Extension) Marshal() ([]byte, error) {
method ToExtension (line 44) | func (e *Extension) ToExtension() (pkix.Extension, error) {
type extensionASN1 (line 25) | type extensionASN1 struct
function GetProvisionerExtension (line 57) | func GetProvisionerExtension(cert *x509.Certificate) (*Extension, bool) {
FILE: authority/provisioner/extension_test.go
function TestExtension_Marshal (line 12) | func TestExtension_Marshal(t *testing.T) {
function TestExtension_ToExtension (line 59) | func TestExtension_ToExtension(t *testing.T) {
function TestGetProvisionerExtension (line 121) | func TestGetProvisionerExtension(t *testing.T) {
FILE: authority/provisioner/gcp.go
constant gcpCertsURL (line 29) | gcpCertsURL = "https://www.googleapis.com/oauth2/v3/certs"
constant gcpIdentityURL (line 32) | gcpIdentityURL = "http://metadata/computeMetadata/v1/instance/service-ac...
type gcpPayload (line 41) | type gcpPayload struct
type gcpGooglePayload (line 49) | type gcpGooglePayload struct
type gcpComputeEnginePayload (line 53) | type gcpComputeEnginePayload struct
type gcpConfig (line 63) | type gcpConfig struct
function newGCPConfig (line 68) | func newGCPConfig() *gcpConfig {
type projectValidator (line 77) | type projectValidator interface
type GCP (line 96) | type GCP struct
method GetID (line 119) | func (p *GCP) GetID() string {
method GetIDForToken (line 128) | func (p *GCP) GetIDForToken() string {
method GetTokenID (line 135) | func (p *GCP) GetTokenID(token string) (string, error) {
method GetName (line 162) | func (p *GCP) GetName() string {
method GetType (line 167) | func (p *GCP) GetType() Type {
method GetEncryptedKey (line 172) | func (p *GCP) GetEncryptedKey() (kid, key string, ok bool) {
method GetIdentityURL (line 177) | func (p *GCP) GetIdentityURL(audience string) string {
method GetIdentityToken (line 189) | func (p *GCP) GetIdentityToken(subject, caURL string) (string, error) {
method Init (line 218) | func (p *GCP) Init(config Config) (err error) {
method AuthorizeSign (line 264) | func (p *GCP) AuthorizeSign(ctx context.Context, token string) ([]Sign...
method AuthorizeRenew (line 326) | func (p *GCP) AuthorizeRenew(ctx context.Context, cert *x509.Certifica...
method assertConfig (line 331) | func (p *GCP) assertConfig() {
method authorizeToken (line 340) | func (p *GCP) authorizeToken(ctx context.Context, token string) (*gcpP...
method AuthorizeSSHSign (line 419) | func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]S...
method genHostOptions (line 497) | func (p *GCP) genHostOptions(_ context.Context, claims *gcpPayload) (S...
method genUserOptions (line 513) | func (p *GCP) genUserOptions(_ context.Context, claims *gcpPayload) (S...
method isUnauthorizedToIssueSSHCert (line 523) | func (p *GCP) isUnauthorizedToIssueSSHCert(certType string) error {
function FormatServiceAccountUsername (line 509) | func FormatServiceAccountUsername(serviceAccountID string) string {
FILE: authority/provisioner/gcp/projectvalidator.go
type ProjectValidator (line 12) | type ProjectValidator struct
method ValidateProject (line 16) | func (p *ProjectValidator) ValidateProject(_ context.Context, projectI...
type OrganizationValidator (line 30) | type OrganizationValidator struct
method ValidateProject (line 55) | func (p *OrganizationValidator) ValidateProject(ctx context.Context, p...
function NewOrganizationValidator (line 36) | func NewOrganizationValidator(projectIDs []string, organizationID string...
FILE: authority/provisioner/gcp/projectvalidator_test.go
function TestProjectValidator_ValidateProject (line 11) | func TestProjectValidator_ValidateProject(t *testing.T) {
function TestNewOrganizationValidator (line 41) | func TestNewOrganizationValidator(t *testing.T) {
function TestOrganizationValidator_ValidateProject (line 84) | func TestOrganizationValidator_ValidateProject(t *testing.T) {
FILE: authority/provisioner/gcp_test.go
function TestGCP_Getters (line 27) | func TestGCP_Getters(t *testing.T) {
function TestGCP_GetTokenID (line 53) | func TestGCP_GetTokenID(t *testing.T) {
function TestGCP_GetIdentityToken (line 108) | func TestGCP_GetIdentityToken(t *testing.T) {
function TestGCP_Init (line 162) | func TestGCP_Init(t *testing.T) {
function TestGCP_authorizeToken (line 228) | func TestGCP_authorizeToken(t *testing.T) {
function TestGCP_AuthorizeSign (line 424) | func TestGCP_AuthorizeSign(t *testing.T) {
function TestGCP_AuthorizeSSHSign (line 598) | func TestGCP_AuthorizeSSHSign(t *testing.T) {
function TestGCP_AuthorizeRenew (line 738) | func TestGCP_AuthorizeRenew(t *testing.T) {
FILE: authority/provisioner/jwk.go
type jwtPayload (line 21) | type jwtPayload struct
type stepPayload (line 28) | type stepPayload struct
type cnfPayload (line 33) | type cnfPayload struct
type JWK (line 39) | type JWK struct
method GetID (line 53) | func (p *JWK) GetID() string {
method GetIDForToken (line 62) | func (p *JWK) GetIDForToken() string {
method GetTokenID (line 67) | func (p *JWK) GetTokenID(ott string) (string, error) {
method GetName (line 85) | func (p *JWK) GetName() string {
method GetType (line 90) | func (p *JWK) GetType() Type {
method GetEncryptedKey (line 95) | func (p *JWK) GetEncryptedKey() (string, string, bool) {
method Init (line 100) | func (p *JWK) Init(config Config) (err error) {
method authorizeToken (line 117) | func (p *JWK) authorizeToken(token string, audiences []string) (*jwtPa...
method AuthorizeRevoke (line 152) | func (p *JWK) AuthorizeRevoke(_ context.Context, token string) error {
method AuthorizeSign (line 159) | func (p *JWK) AuthorizeSign(ctx context.Context, token string) ([]Sign...
method AuthorizeRenew (line 219) | func (p *JWK) AuthorizeRenew(ctx context.Context, cert *x509.Certifica...
method AuthorizeSSHSign (line 225) | func (p *JWK) AuthorizeSSHSign(_ context.Context, token string) ([]Sig...
method AuthorizeSSHRevoke (line 302) | func (p *JWK) AuthorizeSSHRevoke(_ context.Context, token string) error {
FILE: authority/provisioner/jwk_test.go
function TestJWK_Getters (line 24) | func TestJWK_Getters(t *testing.T) {
function TestJWK_Init (line 49) | func TestJWK_Init(t *testing.T) {
function TestJWK_authorizeToken (line 113) | func TestJWK_authorizeToken(t *testing.T) {
function TestJWK_AuthorizeRevoke (line 203) | func TestJWK_AuthorizeRevoke(t *testing.T) {
function TestJWK_AuthorizeSign (line 240) | func TestJWK_AuthorizeSign(t *testing.T) {
function TestJWK_AuthorizeRenew (line 351) | func TestJWK_AuthorizeRenew(t *testing.T) {
function TestJWK_AuthorizeSSHSign (line 396) | func TestJWK_AuthorizeSSHSign(t *testing.T) {
function TestJWK_AuthorizeSign_SSHOptions (line 527) | func TestJWK_AuthorizeSign_SSHOptions(t *testing.T) {
function TestJWK_AuthorizeSSHRevoke (line 635) | func TestJWK_AuthorizeSSHRevoke(t *testing.T) {
FILE: authority/provisioner/k8sSA.go
constant K8sSAName (line 29) | K8sSAName = "k8sSA-default"
constant K8sSAID (line 31) | K8sSAID = "k8ssa/" + K8sSAName
constant k8sSAIssuer (line 32) | k8sSAIssuer = "kubernetes/serviceaccount"
type k8sSAPayload (line 36) | type k8sSAPayload struct
type K8sSA (line 46) | type K8sSA struct
method GetID (line 61) | func (p *K8sSA) GetID() string {
method GetIDForToken (line 70) | func (p *K8sSA) GetIDForToken() string {
method GetTokenID (line 75) | func (p *K8sSA) GetTokenID(string) (string, error) {
method GetName (line 80) | func (p *K8sSA) GetName() string {
method GetType (line 85) | func (p *K8sSA) GetType() Type {
method GetEncryptedKey (line 91) | func (p *K8sSA) GetEncryptedKey() (string, string, bool) {
method Init (line 96) | func (p *K8sSA) Init(config Config) (err error) {
method authorizeToken (line 150) | func (p *K8sSA) authorizeToken(token string, audiences []string) (*k8s...
method AuthorizeRevoke (line 211) | func (p *K8sSA) AuthorizeRevoke(_ context.Context, token string) error {
method AuthorizeSign (line 217) | func (p *K8sSA) AuthorizeSign(_ context.Context, token string) ([]Sign...
method AuthorizeRenew (line 252) | func (p *K8sSA) AuthorizeRenew(ctx context.Context, cert *x509.Certifi...
method AuthorizeSSHSign (line 257) | func (p *K8sSA) AuthorizeSSHSign(_ context.Context, token string) ([]S...
FILE: authority/provisioner/k8sSA_test.go
function TestK8sSA_Getters (line 18) | func TestK8sSA_Getters(t *testing.T) {
function TestK8sSA_authorizeToken (line 38) | func TestK8sSA_authorizeToken(t *testing.T) {
function TestK8sSA_AuthorizeRevoke (line 135) | func TestK8sSA_AuthorizeRevoke(t *testing.T) {
function TestK8sSA_AuthorizeRenew (line 183) | func TestK8sSA_AuthorizeRenew(t *testing.T) {
function TestK8sSA_AuthorizeSign (line 239) | func TestK8sSA_AuthorizeSign(t *testing.T) {
function TestK8sSA_AuthorizeSSHSign (line 314) | func TestK8sSA_AuthorizeSSHSign(t *testing.T) {
FILE: authority/provisioner/keystore.go
constant defaultCacheAge (line 16) | defaultCacheAge = 12 * time.Hour
constant defaultCacheJitter (line 17) | defaultCacheJitter = 1 * time.Hour
type keyStore (line 22) | type keyStore struct
method Get (line 46) | func (ks *keyStore) Get(kid string) (keys []jose.JSONWebKey) {
method reload (line 59) | func (ks *keyStore) reload() {
function newKeyStore (line 31) | func newKeyStore(client HTTPClient, uri string) (*keyStore, error) {
function getKeysFromJWKsURI (line 69) | func getKeysFromJWKsURI(client HTTPClient, uri string) (jose.JSONWebKeyS...
function getCacheAge (line 82) | func getCacheAge(cacheControl string) time.Duration {
function getCacheJitter (line 100) | func getCacheJitter(age time.Duration) time.Duration {
function getExpirationTime (line 113) | func getExpirationTime(age, jitter time.Duration) time.Time {
function abs (line 122) | func abs(n time.Duration) time.Duration {
FILE: authority/provisioner/keystore_test.go
function Test_newKeyStore (line 16) | func Test_newKeyStore(t *testing.T) {
function Test_keyStore (line 56) | func Test_keyStore(t *testing.T) {
function Test_keyStore_noCache (line 100) | func Test_keyStore_noCache(t *testing.T) {
function Test_keyStore_Get (line 128) | func Test_keyStore_Get(t *testing.T) {
function Test_abs (line 156) | func Test_abs(t *testing.T) {
FILE: authority/provisioner/method.go
type Method (line 9) | type Method
method String (line 34) | func (m Method) String() string {
type methodKey (line 12) | type methodKey struct
constant SignMethod (line 16) | SignMethod Method = iota
constant SignIdentityMethod (line 18) | SignIdentityMethod
constant RevokeMethod (line 20) | RevokeMethod
constant RenewMethod (line 22) | RenewMethod
constant SSHSignMethod (line 24) | SSHSignMethod
constant SSHRenewMethod (line 26) | SSHRenewMethod
constant SSHRevokeMethod (line 28) | SSHRevokeMethod
constant SSHRekeyMethod (line 30) | SSHRekeyMethod
function NewContextWithMethod (line 59) | func NewContextWithMethod(ctx context.Context, method Method) context.Co...
function MethodFromContext (line 64) | func MethodFromContext(ctx context.Context) Method {
type tokenKey (line 69) | type tokenKey struct
function NewContextWithToken (line 72) | func NewContextWithToken(ctx context.Context, token string) context.Cont...
function TokenFromContext (line 77) | func TokenFromContext(ctx context.Context) (string, bool) {
type certTypeKey (line 83) | type certTypeKey struct
function NewContextWithCertType (line 86) | func NewContextWithCertType(ctx context.Context, certType string) contex...
function CertTypeFromContext (line 91) | func CertTypeFromContext(ctx context.Context) (string, bool) {
FILE: authority/provisioner/nebula.go
constant NebulaCertHeader (line 33) | NebulaCertHeader jose.HeaderKey = "nebula"
type Nebula (line 46) | type Nebula struct
method Init (line 58) | func (p *Nebula) Init(config Config) (err error) {
method GetID (line 79) | func (p *Nebula) GetID() string {
method GetIDForToken (line 88) | func (p *Nebula) GetIDForToken() string {
method GetTokenID (line 93) | func (p *Nebula) GetTokenID(token string) (string, error) {
method GetName (line 111) | func (p *Nebula) GetName() string {
method GetType (line 116) | func (p *Nebula) GetType() Type {
method GetEncryptedKey (line 121) | func (p *Nebula) GetEncryptedKey() (kid, key string, ok bool) {
method AuthorizeSign (line 126) | func (p *Nebula) AuthorizeSign(_ context.Context, token string) ([]Sig...
method AuthorizeSSHSign (line 182) | func (p *Nebula) AuthorizeSSHSign(_ context.Context, token string) ([]...
method AuthorizeRenew (line 282) | func (p *Nebula) AuthorizeRenew(ctx context.Context, crt *x509.Certifi...
method AuthorizeRevoke (line 287) | func (p *Nebula) AuthorizeRevoke(context.Context, string) error {
method AuthorizeSSHRevoke (line 292) | func (p *Nebula) AuthorizeSSHRevoke(context.Context, string) error {
method AuthorizeSSHRenew (line 297) | func (p *Nebula) AuthorizeSSHRenew(context.Context, string) (*ssh.Cert...
method AuthorizeSSHRekey (line 302) | func (p *Nebula) AuthorizeSSHRekey(context.Context, string) (*ssh.Cert...
method authorizeToken (line 306) | func (p *Nebula) authorizeToken(token string, audiences []string) (neb...
type nebulaSANsValidator (line 388) | type nebulaSANsValidator struct
method Valid (line 395) | func (v nebulaSANsValidator) Valid(req *x509.CertificateRequest) error {
type nebulaPrincipalsValidator (line 443) | type nebulaPrincipalsValidator struct
method Valid (line 450) | func (v nebulaPrincipalsValidator) Valid(got SignSSHOptions) error {
FILE: authority/provisioner/nebula_test.go
function mustNebulaPrefix (line 29) | func mustNebulaPrefix(t *testing.T, s string) netip.Prefix {
function mustNebulaCA (line 36) | func mustNebulaCA(t *testing.T) (cert.Certificate, ed25519.PrivateKey) {
function mustExpiredNebulaCA (line 58) | func mustExpiredNebulaCA(t *testing.T) (cert.Certificate, ed25519.Privat...
function mustNebulaP256CA (line 80) | func mustNebulaP256CA(t *testing.T) (cert.Certificate, *ecdsa.PrivateKey) {
function mustNebulaCert (line 107) | func mustNebulaCert(t *testing.T, name string, network netip.Prefix, gro...
function mustNebulaP256Cert (line 132) | func mustNebulaP256Cert(t *testing.T, name string, network netip.Prefix,...
function mustNebulaProvisioner (line 162) | func mustNebulaProvisioner(t *testing.T) (*Nebula, cert.Certificate, ed2...
function mustNebulaP256Provisioner (line 186) | func mustNebulaP256Provisioner(t *testing.T) (*Nebula, cert.Certificate,...
function mustNebulaToken (line 210) | func mustNebulaToken(t *testing.T, sub, iss, aud string, iat time.Time, ...
function mustNebulaSSHToken (line 246) | func mustNebulaSSHToken(t *testing.T, sub, iss, aud string, iat time.Tim...
function TestNebula_Init (line 287) | func TestNebula_Init(t *testing.T) {
function TestNebula_GetID (line 345) | func TestNebula_GetID(t *testing.T) {
function TestNebula_GetIDForToken (line 371) | func TestNebula_GetIDForToken(t *testing.T) {
function TestNebula_GetTokenID (line 394) | func TestNebula_GetTokenID(t *testing.T) {
function TestNebula_GetName (line 433) | func TestNebula_GetName(t *testing.T) {
function TestNebula_GetType (line 456) | func TestNebula_GetType(t *testing.T) {
function TestNebula_GetEncryptedKey (line 479) | func TestNebula_GetEncryptedKey(t *testing.T) {
function TestNebula_AuthorizeSign (line 505) | func TestNebula_AuthorizeSign(t *testing.T) {
function TestNebula_AuthorizeSSHSign (line 546) | func TestNebula_AuthorizeSSHSign(t *testing.T) {
function TestNebula_AuthorizeRenew (line 615) | func TestNebula_AuthorizeRenew(t *testing.T) {
function TestNebula_AuthorizeRevoke (line 655) | func TestNebula_AuthorizeRevoke(t *testing.T) {
function TestNebula_AuthorizeSSHRevoke (line 689) | func TestNebula_AuthorizeSSHRevoke(t *testing.T) {
function TestNebula_AuthorizeSSHRenew (line 730) | func TestNebula_AuthorizeSSHRenew(t *testing.T) {
function TestNebula_AuthorizeSSHRekey (line 760) | func TestNebula_AuthorizeSSHRekey(t *testing.T) {
function TestNebula_authorizeToken (line 792) | func TestNebula_authorizeToken(t *testing.T) {
function TestNebula_authorizeToken_P256 (line 899) | func TestNebula_authorizeToken_P256(t *testing.T) {
function Test_nebulaSANsValidator_Valid (line 1006) | func Test_nebulaSANsValidator_Valid(t *testing.T) {
function Test_nebulaPrincipalsValidator_Valid (line 1079) | func Test_nebulaPrincipalsValidator_Valid(t *testing.T) {
FILE: authority/provisioner/noop.go
type noop (line 11) | type noop struct
method GetID (line 13) | func (p *noop) GetID() string {
method GetIDForToken (line 17) | func (p *noop) GetIDForToken() string {
method GetTokenID (line 21) | func (p *noop) GetTokenID(string) (string, error) {
method GetName (line 25) | func (p *noop) GetName() string {
method GetType (line 28) | func (p *noop) GetType() Type {
method GetEncryptedKey (line 32) | func (p *noop) GetEncryptedKey() (kid, key string, ok bool) {
method Init (line 36) | func (p *noop) Init(Config) error {
method AuthorizeSign (line 40) | func (p *noop) AuthorizeSign(context.Context, string) ([]SignOption, e...
method AuthorizeRenew (line 44) | func (p *noop) AuthorizeRenew(context.Context, *x509.Certificate) error {
method AuthorizeRevoke (line 48) | func (p *noop) AuthorizeRevoke(context.Context, string) error {
method AuthorizeSSHSign (line 52) | func (p *noop) AuthorizeSSHSign(context.Context, string) ([]SignOption...
method AuthorizeSSHRenew (line 56) | func (p *noop) AuthorizeSSHRenew(context.Context, string) (*ssh.Certif...
method AuthorizeSSHRevoke (line 61) | func (p *noop) AuthorizeSSHRevoke(context.Context, string) error {
method AuthorizeSSHRekey (line 65) | func (p *noop) AuthorizeSSHRekey(context.Context, string) (*ssh.Certif...
FILE: authority/provisioner/noop_test.go
function Test_noop (line 11) | func Test_noop(t *testing.T) {
FILE: authority/provisioner/oidc.go
type openIDConfiguration (line 26) | type openIDConfiguration struct
method Validate (line 32) | func (c openIDConfiguration) Validate() error {
type openIDPayload (line 44) | type openIDPayload struct
method IsAdmin (line 55) | func (o *openIDPayload) IsAdmin(admins []string) bool {
type OIDC (line 81) | type OIDC struct
method GetID (line 112) | func (o *OIDC) GetID() string {
method GetIDForToken (line 121) | func (o *OIDC) GetIDForToken() string {
method GetTokenID (line 127) | func (o *OIDC) GetTokenID(ott string) (string, error) {
method GetName (line 145) | func (o *OIDC) GetName() string {
method GetType (line 150) | func (o *OIDC) GetType() Type {
method GetEncryptedKey (line 155) | func (o *OIDC) GetEncryptedKey() (kid, key string, ok bool) {
method Init (line 160) | func (o *OIDC) Init(config Config) (err error) {
method ValidatePayload (line 214) | func (o *OIDC) ValidatePayload(p openIDPayload) error {
method authorizeToken (line 266) | func (o *OIDC) authorizeToken(token string) (*openIDPayload, error) {
method AuthorizeRevoke (line 303) | func (o *OIDC) AuthorizeRevoke(_ context.Context, token string) error {
method AuthorizeSign (line 318) | func (o *OIDC) AuthorizeSign(_ context.Context, token string) ([]SignO...
method AuthorizeRenew (line 377) | func (o *OIDC) AuthorizeRenew(ctx context.Context, cert *x509.Certific...
method AuthorizeSSHSign (line 382) | func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]...
method AuthorizeSSHRevoke (line 474) | func (o *OIDC) AuthorizeSSHRevoke(_ context.Context, token string) err...
function sanitizeEmail (line 103) | func sanitizeEmail(email string) string {
function getAndDecode (line 488) | func getAndDecode(client HTTPClient, uri string, v interface{}) error {
FILE: authority/provisioner/oidc_test.go
function Test_openIDConfiguration_Validate (line 24) | func Test_openIDConfiguration_Validate(t *testing.T) {
function TestOIDC_Getters (line 52) | func TestOIDC_Getters(t *testing.T) {
function TestOIDC_Init (line 71) | func TestOIDC_Init(t *testing.T) {
function TestOIDC_authorizeToken (line 159) | func TestOIDC_authorizeToken(t *testing.T) {
function TestOIDC_AuthorizeSign (line 277) | func TestOIDC_AuthorizeSign(t *testing.T) {
function TestOIDC_AuthorizeRevoke (line 370) | func TestOIDC_AuthorizeRevoke(t *testing.T) {
function TestOIDC_AuthorizeRenew (line 432) | func TestOIDC_AuthorizeRenew(t *testing.T) {
function TestOIDC_AuthorizeSSHSign (line 478) | func TestOIDC_AuthorizeSSHSign(t *testing.T) {
function TestOIDC_AuthorizeSSHRevoke (line 654) | func TestOIDC_AuthorizeSSHRevoke(t *testing.T) {
function Test_sanitizeEmail (line 710) | func Test_sanitizeEmail(t *testing.T) {
function Test_openIDPayload_IsAdmin (line 730) | func Test_openIDPayload_IsAdmin(t *testing.T) {
FILE: authority/provisioner/options.go
type CertificateOptions (line 19) | type CertificateOptions interface
type certificateOptionsFunc (line 23) | type certificateOptionsFunc
method Options (line 25) | func (fn certificateOptionsFunc) Options(so SignOptions) []x509util.Op...
type Options (line 31) | type Options struct
method GetX509Options (line 41) | func (o *Options) GetX509Options() *X509Options {
method GetSSHOptions (line 49) | func (o *Options) GetSSHOptions() *SSHOptions {
method GetWireOptions (line 58) | func (o *Options) GetWireOptions() (*wire.Options, error) {
method GetWebhooks (line 69) | func (o *Options) GetWebhooks() []*Webhook {
type X509Options (line 77) | type X509Options struct
method HasTemplate (line 101) | func (o *X509Options) HasTemplate() bool {
method GetAllowedNameOptions (line 107) | func (o *X509Options) GetAllowedNameOptions() *policy.X509NameOptions {
method GetDeniedNameOptions (line 116) | func (o *X509Options) GetDeniedNameOptions() *policy.X509NameOptions {
method AreWildcardNamesAllowed (line 123) | func (o *X509Options) AreWildcardNamesAllowed() bool {
function TemplateOptions (line 134) | func TemplateOptions(o *Options, data x509util.TemplateData) (Certificat...
function CustomTemplateOptions (line 142) | func CustomTemplateOptions(o *Options, data x509util.TemplateData, defau...
function unsafeParseSigned (line 199) | func unsafeParseSigned(s string) (map[string]interface{}, error) {
FILE: authority/provisioner/options_test.go
function parseCertificateRequest (line 14) | func parseCertificateRequest(t *testing.T, filename string) *x509.Certif...
function TestOptions_GetX509Options (line 27) | func TestOptions_GetX509Options(t *testing.T) {
function TestOptions_GetSSHOptions (line 49) | func TestOptions_GetSSHOptions(t *testing.T) {
function TestOptions_GetWebhooks (line 71) | func TestOptions_GetWebhooks(t *testing.T) {
function TestProvisionerX509Options_HasTemplate (line 101) | func TestProvisionerX509Options_HasTemplate(t *testing.T) {
function TestTemplateOptions (line 131) | func TestTemplateOptions(t *testing.T) {
function TestCustomTemplateOptions (line 190) | func TestCustomTemplateOptions(t *testing.T) {
function Test_unsafeParseSigned (line 286) | func Test_unsafeParseSigned(t *testing.T) {
function TestX509Options_IsWildcardLiteralAllowed (line 322) | func TestX509Options_IsWildcardLiteralAllowed(t *testing.T) {
FILE: authority/provisioner/policy.go
type policyEngine (line 5) | type policyEngine struct
method getX509 (line 46) | func (p *policyEngine) getX509() policy.X509Policy {
method getSSHHost (line 53) | func (p *policyEngine) getSSHHost() policy.HostPolicy {
method getSSHUser (line 60) | func (p *policyEngine) getSSHUser() policy.UserPolicy {
function newPolicyEngine (line 11) | func newPolicyEngine(options *Options) (*policyEngine, error) {
FILE: authority/provisioner/provisioner.go
type Interface (line 20) | type Interface interface
type HTTPClient (line 39) | type HTTPClient interface
type Uninitialized (line 46) | type Uninitialized struct
method MarshalJSON (line 53) | func (p Uninitialized) MarshalJSON() ([]byte, error) {
type Audiences (line 88) | type Audiences struct
method All (line 99) | func (a Audiences) All() (auds []string) {
method WithFragment (line 112) | func (a Audiences) WithFragment(fragment string) Audiences {
function generateSignAudience (line 176) | func generateSignAudience(caURL, provisionerID string) (string, error) {
type Type (line 185) | type Type
method String (line 214) | func (t Type) String() string {
constant noopType (line 188) | noopType Type = 0
constant TypeJWK (line 190) | TypeJWK Type = 1
constant TypeOIDC (line 192) | TypeOIDC Type = 2
constant TypeGCP (line 194) | TypeGCP Type = 3
constant TypeAWS (line 196) | TypeAWS Type = 4
constant TypeAzure (line 198) | TypeAzure Type = 5
constant TypeACME (line 200) | TypeACME Type = 6
constant TypeX5C (line 202) | TypeX5C Type = 7
constant TypeK8sSA (line 204) | TypeK8sSA Type = 8
constant TypeSSHPOP (line 206) | TypeSSHPOP Type = 9
constant TypeSCEP (line 208) | TypeSCEP Type = 10
constant TypeNebula (line 210) | TypeNebula Type = 11
type SSHKeys (line 244) | type SSHKeys struct
type SCEPKeyManager (line 251) | type SCEPKeyManager interface
type Config (line 258) | type Config struct
type provisioner (line 286) | type provisioner struct
type List (line 291) | type List
method UnmarshalJSON (line 295) | func (l *List) UnmarshalJSON(data []byte) error {
type base (line 352) | type base struct
method AuthorizeSign (line 356) | func (b *base) AuthorizeSign(context.Context, string) ([]SignOption, e...
method AuthorizeRevoke (line 362) | func (b *base) AuthorizeRevoke(context.Context, string) error {
method AuthorizeRenew (line 368) | func (b *base) AuthorizeRenew(context.Context, *x509.Certificate) error {
method AuthorizeSSHSign (line 374) | func (b *base) AuthorizeSSHSign(context.Context, string) ([]SignOption...
method AuthorizeSSHRevoke (line 380) | func (b *base) AuthorizeSSHRevoke(context.Context, string) error {
method AuthorizeSSHRenew (line 386) | func (b *base) AuthorizeSSHRenew(context.Context, string) (*ssh.Certif...
method AuthorizeSSHRekey (line 392) | func (b *base) AuthorizeSSHRekey(context.Context, string) (*ssh.Certif...
type Permissions (line 397) | type Permissions struct
type RAInfo (line 404) | type RAInfo struct
type raProvisioner (line 413) | type raProvisioner struct
method RAInfo (line 419) | func (p *raProvisioner) RAInfo() *RAInfo {
type MockProvisioner (line 424) | type MockProvisioner struct
method GetID (line 444) | func (m *MockProvisioner) GetID() string {
method GetIDForToken (line 452) | func (m *MockProvisioner) GetIDForToken() string {
method GetTokenID (line 460) | func (m *MockProvisioner) GetTokenID(token string) (string, error) {
method GetName (line 471) | func (m *MockProvisioner) GetName() string {
method GetType (line 479) | func (m *MockProvisioner) GetType() Type {
method GetEncryptedKey (line 487) | func (m *MockProvisioner) GetEncryptedKey() (string, string, bool) {
method Init (line 495) | func (m *MockProvisioner) Init(c Config) error {
method AuthorizeSign (line 503) | func (m *MockProvisioner) AuthorizeSign(ctx context.Context, ott strin...
method AuthorizeRevoke (line 511) | func (m *MockProvisioner) AuthorizeRevoke(ctx context.Context, ott str...
method AuthorizeRenew (line 519) | func (m *MockProvisioner) AuthorizeRenew(ctx context.Context, c *x509....
method AuthorizeSSHSign (line 527) | func (m *MockProvisioner) AuthorizeSSHSign(ctx context.Context, ott st...
method AuthorizeSSHRenew (line 535) | func (m *MockProvisioner) AuthorizeSSHRenew(ctx context.Context, ott s...
method AuthorizeSSHRekey (line 543) | func (m *MockProvisioner) AuthorizeSSHRekey(ctx context.Context, ott s...
method AuthorizeSSHRevoke (line 551) | func (m *MockProvisioner) AuthorizeSSHRevoke(ctx context.Context, ott ...
FILE: authority/provisioner/provisioner_test.go
function TestType_String (line 15) | func TestType_String(t *testing.T) {
function TestSanitizeSSHUserPrincipal (line 38) | func TestSanitizeSSHUserPrincipal(t *testing.T) {
function TestDefaultIdentityFunc (line 64) | func TestDefaultIdentityFunc(t *testing.T) {
function TestUnimplementedMethods (line 163) | func TestUnimplementedMethods(t *testing.T) {
function TestUninitialized_MarshalJSON (line 253) | func TestUninitialized_MarshalJSON(t *testing.T) {
FILE: authority/provisioner/scep.go
type SCEP (line 26) | type SCEP struct
method GetID (line 70) | func (s *SCEP) GetID() string {
method GetIDForToken (line 79) | func (s *SCEP) GetIDForToken() string {
method GetName (line 84) | func (s *SCEP) GetName() string {
method GetType (line 89) | func (s *SCEP) GetType() Type {
method GetEncryptedKey (line 94) | func (s *SCEP) GetEncryptedKey() (string, string, bool) {
method GetTokenID (line 100) | func (s *SCEP) GetTokenID(string) (string, error) {
method GetOptions (line 105) | func (s *SCEP) GetOptions() *Options {
method DefaultTLSCertDuration (line 111) | func (s *SCEP) DefaultTLSCertDuration() time.Duration {
method Init (line 250) | func (s *SCEP) Init(config Config) (err error) {
method AuthorizeSign (line 413) | func (s *SCEP) AuthorizeSign(context.Context, string) ([]SignOption, e...
method GetCapabilities (line 429) | func (s *SCEP) GetCapabilities() []string {
method ShouldIncludeRootInChain (line 437) | func (s *SCEP) ShouldIncludeRootInChain() bool {
method ShouldIncludeIntermediateInChain (line 446) | func (s *SCEP) ShouldIncludeIntermediateInChain() bool {
method GetContentEncryptionAlgorithm (line 452) | func (s *SCEP) GetContentEncryptionAlgorithm() int {
method ValidateChallenge (line 459) | func (s *SCEP) ValidateChallenge(ctx context.Context, csr *x509.Certif...
method NotifySuccess (line 474) | func (s *SCEP) NotifySuccess(ctx context.Context, csr *x509.Certificat...
method NotifyFailure (line 481) | func (s *SCEP) NotifyFailure(ctx context.Context, csr *x509.Certificat...
method selectValidationMethod (line 500) | func (s *SCEP) selectValidationMethod() validationMethod {
method GetDecrypter (line 515) | func (s *SCEP) GetDecrypter() (*x509.Certificate, crypto.Decrypter) {
method GetSigner (line 523) | func (s *SCEP) GetSigner() (*x509.Certificate, crypto.Signer) {
type challengeValidationController (line 115) | type challengeValidationController struct
method Validate (line 152) | func (c *challengeValidationController) Validate(ctx context.Context, ...
function newChallengeValidationController (line 123) | func newChallengeValidationController(client HTTPClient, tw httptranspor...
type notificationController (line 181) | type notificationController struct
method Success (line 207) | func (c *notificationController) Success(ctx context.Context, csr *x50...
method Failure (line 223) | func (c *notificationController) Failure(ctx context.Context, csr *x50...
function newNotificationController (line 189) | func newNoti
Condensed preview — 543 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,241K chars).
[
{
"path": ".VERSION",
"chars": 12,
"preview": "$Format:%d$\n"
},
{
"path": ".dockerignore",
"chars": 47,
"preview": "bin\ncoverage.txt\n*.test\n*.out\n.travis-releases\n"
},
{
"path": ".gitattributes",
"chars": 22,
"preview": ".VERSION export-subst\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug-report.yml",
"chars": 1477,
"preview": "name: Bug Report\ndescription: File a bug report\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"needs triage\"]\nbody:\n - type: markdow"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 327,
"preview": "blank_issues_enabled: true\ncontact_links:\n - name: Ask on Discord\n url: https://discord.gg/7xgjhVAg6g\n about: You"
},
{
"path": ".github/ISSUE_TEMPLATE/documentation-request.md",
"chars": 762,
"preview": "---\nname: Documentation Request\nabout: Request documentation for a feature\ntitle: '[Docs]:'\nlabels: docs, needs triage\na"
},
{
"path": ".github/ISSUE_TEMPLATE/enhancement.md",
"chars": 735,
"preview": "---\nname: Enhancement\nabout: Suggest an enhancement to step-ca\ntitle: ''\nlabels: enhancement, needs triage\nassignees: ''"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE",
"chars": 572,
"preview": "<!---\nPlease provide answers in the spaces below each prompt, where applicable.\nNot every PR requires responses for each"
},
{
"path": ".github/dependabot.yml",
"chars": 602,
"preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
},
{
"path": ".github/workflows/actionci.yml",
"chars": 466,
"preview": "name: Action CI\n\non:\n push:\n tags-ignore:\n - 'v*'\n branches:\n - \"master\"\n pull_request:\n workflow_call:\n\n"
},
{
"path": ".github/workflows/ci.yml",
"chars": 652,
"preview": "name: CI\n\non:\n push:\n tags-ignore:\n - 'v*'\n branches:\n - \"master\"\n pull_request:\n workflow_call:\n secr"
},
{
"path": ".github/workflows/code-scan-cron.yml",
"chars": 199,
"preview": "on:\n schedule:\n - cron: '0 0 * * *'\n\npermissions:\n actions: read\n contents: read\n security-events: write\n\njobs:\n "
},
{
"path": ".github/workflows/dependabot-auto-merge.yml",
"chars": 232,
"preview": "name: Dependabot auto-merge\non: pull_request\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n dependabot-"
},
{
"path": ".github/workflows/publish-packages.yml",
"chars": 2543,
"preview": "name: Publish to packages.smallstep.com\n\n# Independently publish packages to Red Hat (RPM) and Debian (DEB) repositories"
},
{
"path": ".github/workflows/release.yml",
"chars": 3494,
"preview": "name: Create Release & Upload Assets\n\non:\n push:\n # Sequence of patterns matched against refs/tags\n tags:\n - '"
},
{
"path": ".github/workflows/triage.yml",
"chars": 314,
"preview": "name: Add Issues and PRs to Triage\n\non:\n issues:\n types:\n - opened\n - reopened\n pull_request_target:\n "
},
{
"path": ".github/zizmor.yml",
"chars": 208,
"preview": "rules:\n unpinned-uses:\n config:\n policies:\n \"smallstep/*\": ref-pin\n secrets-inherit:\n disable: true\n"
},
{
"path": ".gitignore",
"chars": 372,
"preview": "# Binaries for programs and plugins\n/bin\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Go Workspaces\ngo.work\ngo.work.sum\n\n# Test bi"
},
{
"path": ".goreleaser.yml",
"chars": 13618,
"preview": "# Documentation: https://goreleaser.com/customization/\n# yaml-language-server: $schema=https://goreleaser.com/static/sch"
},
{
"path": ".version.sh",
"chars": 203,
"preview": "#!/usr/bin/env sh\nread -r firstline < .VERSION\nlast_half=\"${firstline##*tag: }\"\ncase \"$last_half\" in\n v*)\n ver"
},
{
"path": "CHANGELOG.md",
"chars": 24759,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "CONTRIBUTING.md",
"chars": 5964,
"preview": "# Contributing to `step certificates`\n\nWe welcome contributions to `step certificates` of any kind including\ndocumentati"
},
{
"path": "LICENSE",
"chars": 11351,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Makefile",
"chars": 4653,
"preview": "PKG?=github.com/smallstep/certificates/cmd/step-ca\nBINNAME?=step-ca\n\n# Set V to 1 for verbose output from the Makefile\nQ"
},
{
"path": "README.md",
"chars": 10348,
"preview": "# step-ca\n\n[](https://github.com/smal"
},
{
"path": "SECURITY.md",
"chars": 440,
"preview": "We appreciate any effort to discover and disclose security vulnerabilities responsibly.\n\nIf you would like to report a v"
},
{
"path": "acme/account.go",
"chars": 3911,
"preview": "package acme\n\nimport (\n\t\"crypto\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"go.step.sm/crypto/jose\"\n\n\t\"github.com/sm"
},
{
"path": "acme/account_test.go",
"chars": 4024,
"preview": "package acme\n\nimport (\n\t\"crypto\"\n\t\"encoding/base64\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"go.step.sm/crypto/jos"
},
{
"path": "acme/api/account.go",
"chars": 7151,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"net/http\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/small"
},
{
"path": "acme/api/account_test.go",
"chars": 33806,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n"
},
{
"path": "acme/api/eab.go",
"chars": 5367,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\n\t\"go.step.sm/crypto/jose\"\n\n\t\"github.com/smallstep/certifica"
},
{
"path": "acme/api/eab_test.go",
"chars": 41236,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"go.s"
},
{
"path": "acme/api/handler.go",
"chars": 13260,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"encoding/pem\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.co"
},
{
"path": "acme/api/handler_test.go",
"chars": 27590,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"encoding/pem\"\n\t\"fmt\"\n\t\"io\"\n\t\"n"
},
{
"path": "acme/api/middleware.go",
"chars": 20865,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"crypto/rsa\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strings\"\n\n\t\"go.step.sm/c"
},
{
"path": "acme/api/middleware_test.go",
"chars": 60808,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/htt"
},
{
"path": "acme/api/order.go",
"chars": 15795,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"strings\""
},
{
"path": "acme/api/order_test.go",
"chars": 92716,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\""
},
{
"path": "acme/api/revoke.go",
"chars": 10128,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"string"
},
{
"path": "acme/api/revoke_test.go",
"chars": 41605,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/ecdsa\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"crypto"
},
{
"path": "acme/api/wire_integration_test.go",
"chars": 18332,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/ed25519\"\n\t\"crypto/rand\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding"
},
{
"path": "acme/authorization.go",
"chars": 1662,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n)\n\n// Authorization representst an ACME Authorization.\ntype A"
},
{
"path": "acme/authorization_test.go",
"chars": 3808,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/assert\"\n)\n\nfunc Te"
},
{
"path": "acme/certificate.go",
"chars": 272,
"preview": "package acme\n\nimport (\n\t\"crypto/x509\"\n)\n\n// Certificate options with which to create and store a cert object.\ntype Certi"
},
{
"path": "acme/challenge.go",
"chars": 58457,
"preview": "package acme\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/ecdsa\"\n\t\"crypto/ed25519\"\n\t\"crypto/elliptic\"\n\t\"crypto/rsa\"\n"
},
{
"path": "acme/challenge_test.go",
"chars": 166352,
"preview": "package acme\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"c"
},
{
"path": "acme/challenge_tpmsimulator_test.go",
"chars": 32673,
"preview": "//go:build tpmsimulator\n\npackage acme\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/asn1\"\n\t\""
},
{
"path": "acme/challenge_wire_test.go",
"chars": 84816,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/ed25519\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"encoding/pem\"\n\t\"erro"
},
{
"path": "acme/client.go",
"chars": 2135,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n)\n\n// Client is the interface used to verify "
},
{
"path": "acme/common.go",
"chars": 6717,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"time\"\n\n\t\"github.com/smallstep/certificates/authority\"\n\t\"github.com/sm"
},
{
"path": "acme/db/nosql/account.go",
"chars": 4105,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificate"
},
{
"path": "acme/db/nosql/account_test.go",
"chars": 21636,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/"
},
{
"path": "acme/db/nosql/authz.go",
"chars": 4694,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificate"
},
{
"path": "acme/db/nosql/authz_test.go",
"chars": 22548,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github."
},
{
"path": "acme/db/nosql/certificate.go",
"chars": 3962,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"encoding/pem\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"g"
},
{
"path": "acme/db/nosql/certificate_test.go",
"chars": 13464,
"preview": "package nosql\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"encoding/pem\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t"
},
{
"path": "acme/db/nosql/challenge.go",
"chars": 3061,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/smallstep/nosql\"\n\n\t\""
},
{
"path": "acme/db/nosql/challenge_test.go",
"chars": 13565,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/"
},
{
"path": "acme/db/nosql/eab.go",
"chars": 12553,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"encoding/json\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.c"
},
{
"path": "acme/db/nosql/eab_test.go",
"chars": 52670,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/pkg/"
},
{
"path": "acme/db/nosql/nonce.go",
"chars": 1545,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certifica"
},
{
"path": "acme/db/nosql/nonce_test.go",
"chars": 4797,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/"
},
{
"path": "acme/db/nosql/nosql.go",
"chars": 3269,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\tnosqlDB \"github.com/smallstep/nos"
},
{
"path": "acme/db/nosql/nosql_test.go",
"chars": 3461,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/assert\"\n\t\"github.com/smal"
},
{
"path": "acme/db/nosql/order.go",
"chars": 5993,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/cer"
},
{
"path": "acme/db/nosql/order_test.go",
"chars": 31816,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com"
},
{
"path": "acme/db/nosql/wire.go",
"chars": 3482,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/smallstep/certificates/acme\"\n\t\"github.c"
},
{
"path": "acme/db/nosql/wire_test.go",
"chars": 10103,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/smallstep/certificates/ac"
},
{
"path": "acme/db.go",
"chars": 17350,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// ErrNotFound is an error that should be"
},
{
"path": "acme/db_test.go",
"chars": 758,
"preview": "package acme\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestIsErrNotFound(t *testing.T) {\n\ttype args "
},
{
"path": "acme/errors.go",
"chars": 14187,
"preview": "package acme\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificates"
},
{
"path": "acme/errors_test.go",
"chars": 1625,
"preview": "package acme\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/"
},
{
"path": "acme/linker.go",
"chars": 8178,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/go-chi/chi/v5\"\n\t\"github."
},
{
"path": "acme/linker_test.go",
"chars": 13929,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/smallstep/assert\"\n\t\"github.com/smal"
},
{
"path": "acme/nonce.go",
"chars": 171,
"preview": "package acme\n\n// Nonce represents an ACME nonce type.\ntype Nonce string\n\n// String implements the ToString interface.\nfu"
},
{
"path": "acme/order.go",
"chars": 20930,
"preview": "package acme\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/subtle\"\n\t\"crypto/x509\"\n\t\"encoding/asn1\"\n\t\"encoding/json\"\n\t\"errors\"\n\t"
},
{
"path": "acme/order_test.go",
"chars": 80076,
"preview": "package acme\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/asn1\"\n\t\"encoding/json\"\n\t\"fmt\"\n"
},
{
"path": "acme/status.go",
"chars": 647,
"preview": "package acme\n\n// Status represents an ACME status.\ntype Status string\n\nvar (\n\t// StatusValid -- valid\n\tStatusValid = Sta"
},
{
"path": "acme/wire/id.go",
"chars": 2220,
"preview": "package wire\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n)\n\ntype UserID struct {\n\tName string `j"
},
{
"path": "acme/wire/id_test.go",
"chars": 4043,
"preview": "package wire\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestParseUserID(t *testing.T)"
},
{
"path": "api/api.go",
"chars": 20210,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/dsa\" //nolint:staticcheck // support legacy algorithms\n\t\"cr"
},
{
"path": "api/api_test.go",
"chars": 63778,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/dsa\" //nolint:staticcheck // support legacy algorithms\n\t\"cr"
},
{
"path": "api/crl.go",
"chars": 1103,
"preview": "package api\n\nimport (\n\t\"encoding/pem\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/smallstep/certificates/api/render\"\n\t\"github.com/"
},
{
"path": "api/crl_test.go",
"chars": 3679,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/pem\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\t\"time\"\n\n\t\"g"
},
{
"path": "api/log/log.go",
"chars": 2226,
"preview": "// Package log implements API-related logging helpers.\npackage log\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"gith"
},
{
"path": "api/log/log_test.go",
"chars": 3415,
"preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"log/slog\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\t\"unsafe\"\n\n\tpkge"
},
{
"path": "api/models/scep.go",
"chars": 4754,
"preview": "package models\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"errors\"\n\n\t\"github.com/smallstep/certificates/authority/provisioner\""
},
{
"path": "api/read/read.go",
"chars": 1777,
"preview": "// Package read implements request object readers.\npackage read\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t"
},
{
"path": "api/read/read_test.go",
"chars": 3819,
"preview": "package read\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing"
},
{
"path": "api/rekey.go",
"chars": 1812,
"preview": "package api\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/smallstep/certificates/api/read\"\n\t\"github.com/smallstep/certificates/api"
},
{
"path": "api/render/render.go",
"chars": 3234,
"preview": "// Package render implements functionality related to response rendering.\npackage render\n\nimport (\n\t\"encoding/json\"\n\t\"er"
},
{
"path": "api/render/render_test.go",
"chars": 3503,
"preview": "package render\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strconv\"\n\t\"testing\"\n\n\t"
},
{
"path": "api/renew.go",
"chars": 1902,
"preview": "package api\n\nimport (\n\t\"crypto/x509\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/smallstep/certificates/api/render\"\n\t\"github.co"
},
{
"path": "api/revoke.go",
"chars": 3902,
"preview": "package api\n\nimport (\n\t\"math/big\"\n\t\"net/http\"\n\n\t\"golang.org/x/crypto/ocsp\"\n\n\t\"github.com/smallstep/certificates/api/read"
},
{
"path": "api/revoke_test.go",
"chars": 6725,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/htt"
},
{
"path": "api/sign.go",
"chars": 2922,
"preview": "package api\n\nimport (\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"net/http\"\n\n\t\"github.com/smallstep/certificates/api/read\"\n\t\"github"
},
{
"path": "api/ssh.go",
"chars": 16720,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\""
},
{
"path": "api/sshRekey.go",
"chars": 2794,
"preview": "package api\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"golang.org/x/crypto/ssh\"\n\n\t\"github.com/smallstep/certificates/api/read\"\n\t\"g"
},
{
"path": "api/sshRenew.go",
"chars": 3310,
"preview": "package api\n\nimport (\n\t\"crypto/x509\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/smallstep/certificates/"
},
{
"path": "api/sshRevoke.go",
"chars": 2736,
"preview": "package api\n\nimport (\n\t\"net/http\"\n\n\t\"golang.org/x/crypto/ocsp\"\n\n\t\"github.com/smallstep/certificates/api/read\"\n\t\"github.c"
},
{
"path": "api/ssh_test.go",
"chars": 30245,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"crypto/x509\"\n\t\"encoding/ba"
},
{
"path": "authority/admin/api/acme.go",
"chars": 5071,
"preview": "package api\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/smallstep/linkedca\"\n\t\"google.golang.org/protobuf/types/known/time"
},
{
"path": "authority/admin/api/acme_test.go",
"chars": 15834,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"strings\"\n"
},
{
"path": "authority/admin/api/admin.go",
"chars": 5987,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/smallstep/linkedca\"\n\n\t\"github.co"
},
{
"path": "authority/admin/api/admin_test.go",
"chars": 27819,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\t"
},
{
"path": "authority/admin/api/handler.go",
"chars": 6084,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\n\t\"github.com/smallstep/certificates/api\"\n\t\"github.com/smallstep/certificat"
},
{
"path": "authority/admin/api/middleware.go",
"chars": 4276,
"preview": "package api\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/smallstep/linkedca\"\n\n\t\"github.com/smallstep"
},
{
"path": "authority/admin/api/middleware_test.go",
"chars": 21061,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\t"
},
{
"path": "authority/admin/api/policy.go",
"chars": 15191,
"preview": "package api\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\n\t\"github.com/smallstep/linkedca\"\n\n\t\"github.com/smallstep/certifi"
},
{
"path": "authority/admin/api/policy_test.go",
"chars": 80690,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t"
},
{
"path": "authority/admin/api/provisioner.go",
"chars": 6510,
"preview": "package api\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/go-chi/chi/v5\"\n\n\t\"github.com/smallstep/linkedca\"\n\t\"go.step.sm/cry"
},
{
"path": "authority/admin/api/provisioner_test.go",
"chars": 37426,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t"
},
{
"path": "authority/admin/api/webhook.go",
"chars": 6691,
"preview": "package api\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/go-chi/chi/v5\"\n\t\"github.com/smallst"
},
{
"path": "authority/admin/api/webhook_test.go",
"chars": 22419,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t"
},
{
"path": "authority/admin/db/nosql/admin.go",
"chars": 4728,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificate"
},
{
"path": "authority/admin/db/nosql/admin_test.go",
"chars": 32809,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/"
},
{
"path": "authority/admin/db/nosql/nosql.go",
"chars": 2163,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\tnosqlDB \"github.com/smallstep/nos"
},
{
"path": "authority/admin/db/nosql/policy.go",
"chars": 9240,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/smallstep/linkedca\"\n\n\t\"github.com/smallstep/cer"
},
{
"path": "authority/admin/db/nosql/policy_test.go",
"chars": 33364,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/smallstep/assert\"\n\t\"gi"
},
{
"path": "authority/admin/db/nosql/provisioner.go",
"chars": 8930,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificate"
},
{
"path": "authority/admin/db/nosql/provisioner_test.go",
"chars": 40818,
"preview": "package nosql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/"
},
{
"path": "authority/admin/db.go",
"chars": 8213,
"preview": "package admin\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/linkedca\"\n)\n"
},
{
"path": "authority/admin/errors.go",
"chars": 5385,
"preview": "package admin\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificate"
},
{
"path": "authority/administrator/collection.go",
"chars": 7171,
"preview": "package administrator\n\nimport (\n\t\"sort\"\n\t\"sync\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificates/authority/"
},
{
"path": "authority/admins.go",
"chars": 3424,
"preview": "package authority\n\nimport (\n\t\"context\"\n\n\t\"github.com/smallstep/certificates/authority/admin\"\n\t\"github.com/smallstep/cert"
},
{
"path": "authority/authority.go",
"chars": 34298,
"preview": "package authority\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n"
},
{
"path": "authority/authority_test.go",
"chars": 17701,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n\t\"encodi"
},
{
"path": "authority/authorize.go",
"chars": 19440,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"s"
},
{
"path": "authority/authorize_test.go",
"chars": 55384,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/ed25519\"\n\t\"crypto/rand\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"e"
},
{
"path": "authority/config/config.go",
"chars": 14899,
"preview": "package config\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/s"
},
{
"path": "authority/config/config_test.go",
"chars": 10132,
"preview": "package config\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/assert\"\n\t\"github."
},
{
"path": "authority/config/ssh.go",
"chars": 2542,
"preview": "package config\n\nimport (\n\t\"github.com/pkg/errors\"\n\t\"github.com/smallstep/certificates/authority/provisioner\"\n\t\"go.step.s"
},
{
"path": "authority/config/ssh_test.go",
"chars": 1732,
"preview": "package config\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/smallstep/assert\"\n\t\"go.step.sm/crypto/jose\"\n\t\"golang.org/x/"
},
{
"path": "authority/config/tls_options.go",
"chars": 6686,
"preview": "package config\n\nimport (\n\t\"crypto/tls\"\n\t\"fmt\"\n\n\t\"github.com/pkg/errors\"\n)\n\nvar (\n\t// DefaultTLSMinVersion default minimu"
},
{
"path": "authority/config/tls_options_test.go",
"chars": 8943,
"preview": "package config\n\nimport (\n\t\"crypto/tls\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestTLSVersion_Validate(t *testing.T) {\n\ttests := ["
},
{
"path": "authority/config/types.go",
"chars": 1650,
"preview": "package config\n\nimport (\n\t\"encoding/json\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// multiString represents a type that can be enco"
},
{
"path": "authority/config/types_test.go",
"chars": 2803,
"preview": "package config\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc Test_multiString_First(t *testing.T) {\n\ttests := []struct {\n\t\tnam"
},
{
"path": "authority/config.go",
"chars": 1193,
"preview": "package authority\n\nimport \"github.com/smallstep/certificates/authority/config\"\n\n// Config is an alias to support older A"
},
{
"path": "authority/export.go",
"chars": 8069,
"preview": "package authority\n\nimport (\n\t\"encoding/json\"\n\t\"net/url\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/pkg/errors\"\n\t\"go"
},
{
"path": "authority/http_client.go",
"chars": 1375,
"preview": "package authority\n\nimport (\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"net/http\"\n\t\"sync/atomic\"\n\n\t\"github.com/smallstep/certificates"
},
{
"path": "authority/http_client_test.go",
"chars": 3260,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"test"
},
{
"path": "authority/internal/constraints/constraints.go",
"chars": 4291,
"preview": "package constraints\n\nimport (\n\t\"crypto/x509\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/smallstep/certificates/e"
},
{
"path": "authority/internal/constraints/constraints_test.go",
"chars": 14047,
"preview": "package constraints\n\nimport (\n\t\"crypto/x509\"\n\t\"net\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"go.step.sm/crypto/minica\"\n)\n\nfun"
},
{
"path": "authority/internal/constraints/verify.go",
"chars": 10947,
"preview": "// Copyright (c) 2009 The Go Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with"
},
{
"path": "authority/linkedca.go",
"chars": 18299,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/sha256\"\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n\t\"encodin"
},
{
"path": "authority/meter.go",
"chars": 3996,
"preview": "package authority\n\nimport (\n\t\"crypto\"\n\t\"crypto/x509\"\n\t\"io\"\n\n\t\"go.step.sm/crypto/kms\"\n\tkmsapi \"go.step.sm/crypto/kms/apiv"
},
{
"path": "authority/options.go",
"chars": 12669,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x"
},
{
"path": "authority/policy/engine.go",
"chars": 3409,
"preview": "package policy\n\nimport (\n\t\"crypto/x509\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"golang.org/x/crypto/ssh\"\n)\n\n// Engine is a container for mul"
},
{
"path": "authority/policy/options.go",
"chars": 5896,
"preview": "package policy\n\n// Options is a container for authority level x509 and SSH\n// policy configuration.\ntype Options struct "
},
{
"path": "authority/policy/options_test.go",
"chars": 819,
"preview": "package policy\n\nimport (\n\t\"testing\"\n)\n\nfunc TestX509PolicyOptions_IsWildcardLiteralAllowed(t *testing.T) {\n\ttests := []s"
},
{
"path": "authority/policy/policy.go",
"chars": 7610,
"preview": "package policy\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/smallstep/linkedca\"\n\n\t\"github.com/smallstep/certificates/policy\"\n)\n\n// X50"
},
{
"path": "authority/policy/policy_test.go",
"chars": 3923,
"preview": "package policy\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\n\t\"github.com/smallstep/linkedca\"\n)\n\nfunc TestPolic"
},
{
"path": "authority/policy.go",
"chars": 7081,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/smallstep/linkedca\"\n\n\t\"github.com/smallstep/certif"
},
{
"path": "authority/policy_test.go",
"chars": 40049,
"preview": "package authority\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/go-jose/go-jose/v3\"\n\t\"github.com/st"
},
{
"path": "authority/poolhttp/poolhttp.go",
"chars": 2519,
"preview": "package poolhttp\n\nimport (\n\t\"net/http\"\n\t\"sync\"\n\n\t\"github.com/smallstep/certificates/internal/httptransport\"\n)\n\n// Transp"
},
{
"path": "authority/poolhttp/poolhttp_test.go",
"chars": 2983,
"preview": "package poolhttp\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/te"
},
{
"path": "authority/provisioner/acme.go",
"chars": 13029,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/p"
},
{
"path": "authority/provisioner/acme_118_test.go",
"chars": 2113,
"preview": "//go:build go1.18\n\npackage provisioner\n\nimport (\n\t\"bytes\"\n\t\"crypto/x509\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestACME_GetAttestatio"
},
{
"path": "authority/provisioner/acme_119_test.go",
"chars": 1593,
"preview": "//go:build !go1.18\n\npackage provisioner\n\nimport (\n\t\"bytes\"\n\t\"crypto/x509\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestACME_GetAttestati"
},
{
"path": "authority/provisioner/acme_test.go",
"chars": 13893,
"preview": "package provisioner\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/x509\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n"
},
{
"path": "authority/provisioner/aws.go",
"chars": 21642,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"encoding/j"
},
{
"path": "authority/provisioner/aws_certificates.pem",
"chars": 35158,
"preview": "# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/verify-signature.html\n# https://docs.aws.amazon.com/AWSEC2/latest/"
},
{
"path": "authority/provisioner/aws_test.go",
"chars": 31680,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encodi"
},
{
"path": "authority/provisioner/azure.go",
"chars": 17141,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/ht"
},
{
"path": "authority/provisioner/azure_test.go",
"chars": 25794,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encodi"
},
{
"path": "authority/provisioner/claims.go",
"chars": 10654,
"preview": "package provisioner\n\nimport (\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/crypto/ssh\"\n)\n\n// Claims so that individu"
},
{
"path": "authority/provisioner/claims_test.go",
"chars": 1445,
"preview": "package provisioner\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"golang.org/x/crypto/ssh\"\n)\n\nfunc TestClaimer_DefaultSSHCertDuration("
},
{
"path": "authority/provisioner/collection.go",
"chars": 10423,
"preview": "package provisioner\n\nimport (\n\t\"crypto/sha1\" //nolint:gosec // not used for cryptographic security\n\t\"crypto/x509\"\n\t\"enco"
},
{
"path": "authority/provisioner/collection_test.go",
"chars": 12656,
"preview": "package provisioner\n\nimport (\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"reflect\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/"
},
{
"path": "authority/provisioner/controller.go",
"chars": 8473,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"golan"
},
{
"path": "authority/provisioner/controller_test.go",
"chars": 17366,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/s"
},
{
"path": "authority/provisioner/duration.go",
"chars": 1808,
"preview": "package provisioner\n\nimport (\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// Duration is a wrapper around Time"
},
{
"path": "authority/provisioner/duration_test.go",
"chars": 2845,
"preview": "package provisioner\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestNewDuration(t *testing.T) {\n\ttype args struct {\n"
},
{
"path": "authority/provisioner/extension.go",
"chars": 1944,
"preview": "package provisioner\n\nimport (\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"encoding/asn1\"\n)\n\nvar (\n\t// StepOIDRoot is the root O"
},
{
"path": "authority/provisioner/extension_test.go",
"chars": 4408,
"preview": "package provisioner\n\nimport (\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"go.step.sm/crypto/pemutil\"\n)\n\n"
},
{
"path": "authority/provisioner/gcp/projectvalidator.go",
"chars": 1982,
"preview": "package gcp\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\n\t\"google.golang.org/api/cloudresourcemanager/v1\"\n\n\t\"github.com/smallstep/c"
},
{
"path": "authority/provisioner/gcp/projectvalidator_test.go",
"chars": 3922,
"preview": "package gcp\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"google.golang.org/api/cloudresource"
},
{
"path": "authority/provisioner/gcp.go",
"chars": 17649,
"preview": "package provisioner\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/htt"
},
{
"path": "authority/provisioner/gcp_test.go",
"chars": 28353,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encodi"
},
{
"path": "authority/provisioner/jwk.go",
"chars": 10470,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/smal"
},
{
"path": "authority/provisioner/jwk_test.go",
"chars": 25657,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/ht"
},
{
"path": "authority/provisioner/k8sSA.go",
"chars": 10768,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/ecdsa\"\n\t\"crypto/ed25519\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n"
},
{
"path": "authority/provisioner/k8sSA_test.go",
"chars": 11712,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"testing\"\n\t\"time\"\n\n\t\"go.step.sm/cr"
},
{
"path": "authority/provisioner/keystore.go",
"chars": 2819,
"preview": "package provisioner\n\nimport (\n\t\"encoding/json\"\n\t\"math/rand\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pkg/error"
},
{
"path": "authority/provisioner/keystore_test.go",
"chars": 4650,
"preview": "package provisioner\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\""
},
{
"path": "authority/provisioner/method.go",
"chars": 2790,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n)\n\n// Method indicates the action to action that we will perform, it's used as "
},
{
"path": "authority/provisioner/nebula.go",
"chars": 14820,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/ecdh\"\n\t\"crypto/ecdsa\"\n\t\"crypto/ed25519\"\n\t\"crypto/elliptic\"\n\t\"crypto/x5"
},
{
"path": "authority/provisioner/nebula_test.go",
"chars": 33844,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/ecdsa\"\n\t\"crypto/ed25519\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t"
},
{
"path": "authority/provisioner/noop.go",
"chars": 1336,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\n\t\"golang.org/x/crypto/ssh\"\n)\n\n// noop provisioners is a provisi"
},
{
"path": "authority/provisioner/noop_test.go",
"chars": 770,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"testing\"\n\n\t\"github.com/smallstep/assert\"\n)\n\nfunc Test_noop(t *"
},
{
"path": "authority/provisioner/oidc.go",
"chars": 15756,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strings"
},
{
"path": "authority/provisioner/oidc_test.go",
"chars": 30734,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/ht"
},
{
"path": "authority/provisioner/options.go",
"chars": 6378,
"preview": "package provisioner\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/smallstep/cli-utils/st"
},
{
"path": "authority/provisioner/options_test.go",
"chars": 11498,
"preview": "package provisioner\n\nimport (\n\t\"bytes\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"go.step.sm/crypto/pemuti"
},
{
"path": "authority/provisioner/policy.go",
"chars": 1475,
"preview": "package provisioner\n\nimport \"github.com/smallstep/certificates/authority/policy\"\n\ntype policyEngine struct {\n\tx509Policy"
},
{
"path": "authority/provisioner/provisioner.go",
"chars": 17347,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\tstderrors \"errors\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"st"
},
{
"path": "authority/provisioner/provisioner_test.go",
"chars": 8489,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"github.com/go-jose/go-jose/v3\"\n\t\"github.com"
},
{
"path": "authority/provisioner/scep.go",
"chars": 18493,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t\"crypto/subtle\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"fmt\"\n"
},
{
"path": "authority/provisioner/scep_test.go",
"chars": 25362,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"crypto/x509/pkix\"\n\t\"enc"
},
{
"path": "authority/provisioner/sign_options.go",
"chars": 18172,
"preview": "package provisioner\n\nimport (\n\t\"context\"\n\t\"crypto/ecdsa\"\n\t\"crypto/ed25519\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/subtl"
}
]
// ... and 343 more files (download for full content)
About this extraction
This page contains the full source code of the smallstep/certificates GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 543 files (4.5 MB), approximately 1.2M tokens, and a symbol index with 4161 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.