Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Hardware Security Module support #2625

Merged
merged 53 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4b23e18
Hardware Security Module support. Dockerized HSM quicktest and quicks…
aarmam Jul 7, 2021
acfc53a
Update dependencies
aarmam Oct 18, 2021
e608559
fix: pointer to pointer
aarmam Oct 19, 2021
36f9d2a
fix: exclude opaque private keys without exception
aarmam Oct 19, 2021
5bc42c7
fix: separate dockerfile for HSM quickstart and containerized test ex…
aarmam Oct 20, 2021
2f34cdc
fix: Skipped tests that are not applicable when HSM enabled. Changed …
aarmam Oct 25, 2021
f5d1172
fix: Set key as signing key when use not defined
aarmam Oct 25, 2021
3bae30f
fix: Decide key usage from private key attribute
aarmam Oct 25, 2021
bab52ea
feat: Make hardware key manager GenerateKeySet to function same as so…
aarmam Oct 25, 2021
f668c29
feat: Make GenerateKeySet atomic
aarmam Oct 25, 2021
51c3e36
fix: Add EdDSA to test key generators
aarmam Oct 25, 2021
48bc59d
fix: Add stack trace
aarmam Oct 25, 2021
cf52643
fix: Error when unsupported elliptic curve
aarmam Oct 25, 2021
097bceb
feat: Solution accepted
aarmam Oct 25, 2021
630c974
feat: drop methods for finding keys by public/private prefix #2814
aarmam Oct 25, 2021
c6440b1
fix: code coverage
aarmam Oct 25, 2021
f3c7a69
fix: code coverage
aarmam Oct 25, 2021
79b987f
fix: code coverage
aarmam Oct 25, 2021
31597e4
fix: Add stack trace
aarmam Oct 25, 2021
e124852
feat: circleci test-hsm
aarmam Oct 26, 2021
52327bf
fix: update dependencies
aarmam Oct 26, 2021
c83f279
fix: solution accepted
aarmam Oct 27, 2021
3127946
feat: note on EdDSA support
aarmam Oct 27, 2021
3c04041
fix: add build tag hsm
aarmam Nov 2, 2021
d6ebe90
fix: hsm documentation
aarmam Nov 3, 2021
42ba490
docs: add hsm to sidebar
aeneasr Nov 30, 2021
37b837e
fix: revert hydra.jwt.access-token key stradegy generation check
aarmam Dec 2, 2021
28becdd
fix: make updating keys transactional
aarmam Dec 2, 2021
032630f
fix: add missing key generator
aarmam Dec 2, 2021
363ca75
fix: make TestManagerKey/TestManagerKeySet actually execute by refere…
aarmam Dec 2, 2021
a34963d
fix: add UpdateKey/UpdateKeySet to tests
aarmam Dec 2, 2021
4fb3b18
fix: add default key manager type check tests when HSM enabled
aarmam Dec 2, 2021
e74ca16
fix: test for excluding opaque private keys
aarmam Dec 2, 2021
df68f4d
fix: check error when finding keys
aarmam Dec 2, 2021
8d625ad
fix: remove redundant CI steps from test-hsm
aarmam Dec 2, 2021
80baa98
fix: redundant HSM specific assert, test is skipped completely.
aarmam Dec 2, 2021
d3c0695
fix: add unsupported key generator test
aarmam Dec 2, 2021
f3bced1
fix: add GetOrGenerateKeys test
aarmam Dec 2, 2021
423cc99
fix: add hsm buildtag to code coverage
aarmam Dec 3, 2021
0e9ebd4
fix: add default key manager type check tests when HSM enabled
aarmam Dec 3, 2021
07cf744
fix: hsm key manager tests
aarmam Dec 5, 2021
8b9a9d5
fix: jwt strategy tests
aarmam Dec 6, 2021
5a6d5d3
fix: remove redundant error check
aarmam Dec 6, 2021
5f6f1e6
fix: rename method GenerateKeySet to GenerateAndPersistKeySet
aarmam Dec 8, 2021
17c0b52
fix: hsm not supported wording
aarmam Dec 8, 2021
3c7dd77
fix: format documentation
aarmam Dec 8, 2021
2fab67a
fix: remove contributors
aeneasr Dec 25, 2021
18e61e9
chore: code review
aeneasr Dec 27, 2021
3571c71
Merge remote-tracking branch 'origin/master' into feature/hsm
aeneasr Dec 27, 2021
6965b87
chore: code review
aeneasr Dec 27, 2021
ff11892
feat: add key manager strategy
aarmam Jan 7, 2022
af52789
Merge remote-tracking branch 'origin/master' into feature/hsm
aeneasr Jan 11, 2022
0ee34ae
docs: clarify fallback strategy
aeneasr Jan 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,49 @@ jobs:
- golangci/install
- golangci/lint
- run: make .bin/go-acc
- run: .bin/go-acc -o coverage.out ./... -- -failfast -timeout=20m -tags sqlite
- run: .bin/go-acc -o coverage.out ./... -- -failfast -timeout=20m -tags=sqlite,hsm
# Running race conditions requires parallel tests, otherwise it's worthless (which is the case)
# - run: go test -race -short $(go list ./... | grep -v cmd)
- run: |
bash <(curl -s https://codecov.io/bash)

test-hsm:
docker:
- image: cimg/go:1.16-node
environment:
- HSM_ENABLED=true
- HSM_LIBRARY=/usr/lib/softhsm/libsofthsm2.so
- HSM_TOKEN_LABEL=hydra
- HSM_PIN=1234
- TEST_DATABASE_POSTGRESQL=postgres://test:test@localhost:5432/postgres?sslmode=disable
- TEST_DATABASE_MYSQL=mysql://root:test@(localhost:3306)/mysql?multiStatements=true&parseTime=true
- TEST_DATABASE_COCKROACHDB=cockroach://root@localhost:26257/defaultdb?sslmode=disable
- image: postgres:9.6
environment:
- POSTGRES_USER=test
- POSTGRES_PASSWORD=test
- POSTGRES_DB=postgres
- image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=test
- image: cockroachdb/cockroach:v20.2.5
command: start-single-node --insecure
steps:
- checkout
- setup_remote_docker

- go/load-cache:
key: ory-hydra-go-mod-v1
- go/mod-download
- go/save-cache:
key: ory-hydra-go-mod-v1

- run: sudo apt update
- run: sudo apt install -y softhsm opensc
- run: sudo rm -rf /var/lib/softhsm/tokens; sudo mkdir -p /var/lib/softhsm/tokens; sudo chmod -R a+rwx /var/lib/softhsm; sudo chmod a+rx /etc/softhsm; sudo chmod a+r /etc/softhsm/*
- run: pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --init-token --so-pin 0000 --init-pin --pin 1234 --label hydra
- run: go test -p 1 -v -failfast -short -timeout=20m -tags=sqlite,hsm ./...

test-e2e:
docker:
- image: oryd/e2e-env:latest
Expand Down Expand Up @@ -158,13 +195,18 @@ workflows:
filters:
tags:
only: /.*/
- test-hsm:
filters:
tags:
only: /.*/
- test-e2e:
filters:
tags:
only: /.*/
- changelog/generate:
requires:
- test
- test-hsm
- test-e2e
- docs/build
# - test-legacy-migrations-mysql
Expand All @@ -180,6 +222,7 @@ workflows:
specignorepgks: internal/httpclient gopkg.in/square/go-jose.v2
requires:
- test
- test-hsm
- test-e2e
# - test-legacy-migrations-mysql
# - test-legacy-migrations-cockroach
Expand All @@ -193,6 +236,7 @@ workflows:
swagpath: spec/api.json
requires:
- test
- test-hsm
- sdk/generate
- goreleaser/release
- docs/build
Expand All @@ -217,6 +261,7 @@ workflows:
- goreleaser/release:
requires:
- test
- test-hsm
- test-e2e
- changelog/generate
# - test-legacy-migrations-mysql
Expand Down
57 changes: 57 additions & 0 deletions .docker/Dockerfile-hsm
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
FROM golang:1.16-alpine AS builder

RUN apk -U --no-cache add build-base git gcc bash

WORKDIR /go/src/github.com/ory/hydra

ADD go.mod go.mod
ADD go.sum go.sum

ENV GO111MODULE on
ENV CGO_ENABLED 1

RUN go mod download

ADD . .

FROM builder as build-hydra
RUN go build -tags=sqlite,hsm -o /usr/bin/hydra

FROM builder as test-hsm
ENV HSM_ENABLED=true
ENV HSM_LIBRARY=/usr/lib/softhsm/libsofthsm2.so
ENV HSM_TOKEN_LABEL=hydra
ENV HSM_PIN=1234

RUN apk -U --no-cache add softhsm opensc; \
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --init-token --so-pin 0000 --init-pin --pin 1234 --label hydra; \
go test -p 1 -v -failfast -short -tags=sqlite,hsm ./...

FROM alpine:3.14.2

RUN apk -U --no-cache add softhsm opensc; \
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --slot 0 --init-token --so-pin 0000 --init-pin --pin 1234 --label hydra

RUN addgroup -S ory; \
adduser -S ory -G ory -D -h /home/ory -s /bin/nologin; \
chown -R ory:ory /home/ory; \
chown -R ory:ory /var/lib/softhsm/tokens

COPY --from=build-hydra /usr/bin/hydra /usr/bin/hydra

# By creating the sqlite folder as the ory user, the mounted volume will be owned by ory:ory, which
# is required for read/write of SQLite.
RUN mkdir -p /var/lib/sqlite
RUN chown ory:ory /var/lib/sqlite
VOLUME /var/lib/sqlite

# Exposing the ory home directory
VOLUME /home/ory

# Declare the standard ports used by hydra (4433 for public service endpoint, 4434 for admin service endpoint)
EXPOSE 4444 4445

USER ory

ENTRYPOINT ["hydra"]
CMD ["serve"]
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@ dist
.bin
test/e2e
test/mock-*
test/stub
cypress
12 changes: 4 additions & 8 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ builds:
-
id: hydra-sqlite-darwin
flags:
- -tags
- sqlite
- -tags=sqlite,hsm
ldflags:
- -s -w -X github.com/ory/hydra/driver/config.Version={{.Tag}} -X github.com/ory/hydra/driver/config.Commit={{.FullCommit}} -X github.com/ory/hydra/driver/config.Date={{.Date}}
# - "-extldflags '-static'"
Expand All @@ -32,8 +31,7 @@ builds:
-
id: hydra-sqlite-linux
flags:
- -tags
- sqlite
- -tags=sqlite,hsm
ldflags:
- -s -w -X github.com/ory/hydra/driver/config.Version={{.Tag}} -X github.com/ory/hydra/driver/config.Commit={{.FullCommit}} -X github.com/ory/hydra/driver/config.Date={{.Date}}
binary: hydra
Expand All @@ -46,8 +44,7 @@ builds:
-
id: hydra-sqlite-linux-libmusl
flags:
- -tags
- sqlite
- -tags=sqlite,hsm
ldflags:
- -s -w -X github.com/ory/hydra/driver/config.Version={{.Tag}} -X github.com/ory/hydra/driver/config.Commit={{.FullCommit}} -X github.com/ory/hydra/driver/config.Date={{.Date}}
binary: hydra
Expand All @@ -61,8 +58,7 @@ builds:
-
id: hydra-sqlite-windows
flags:
- -tags
- sqlite
- -tags=sqlite,hsm
ldflags:
- -s -w -X github.com/ory/hydra/driver/config.Version={{.Tag}} -X github.com/ory/hydra/driver/config.Commit={{.FullCommit}} -X github.com/ory/hydra/driver/config.Date={{.Date}}
- "-extldflags '-static'"
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ e2e: node_modules test-resetdb
quicktest:
go test -failfast -short -tags sqlite ./...

.PHONY: quicktest-hsm
quicktest-hsm:
aeneasr marked this conversation as resolved.
Show resolved Hide resolved
docker build --progress=plain -f .docker/Dockerfile-hsm --target test-hsm .

# Formats the code
.PHONY: format
format: .bin/goimports node_modules docs/node_modules contributors
Expand Down
4 changes: 4 additions & 0 deletions cmd/cli/handler_import_jwk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func TestImportJSONWebKey(t *testing.T) {
reg := internal.NewRegistryMemory(t, conf)
router := x.NewRouterPublic()

if conf.HsmEnabled() {
t.Skip("Skipping test. Keys cannot be imported when Hardware Security Module is enabled")
}

h := reg.KeyHandler()
m := reg.KeyManager()

Expand Down
17 changes: 13 additions & 4 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
"testing"
"time"

"github.com/ory/hydra/internal"

"github.com/phayes/freeport"
"github.com/stretchr/testify/assert"

Expand Down Expand Up @@ -73,13 +75,15 @@ func init() {
func TestExecute(t *testing.T) {
frontend := fmt.Sprintf("https://localhost:%d/", frontendPort)
backend := fmt.Sprintf("https://localhost:%d/", backendPort)
conf := internal.NewConfigurationWithDefaults()

rootCmd := NewRootCmd()

for _, c := range []struct {
args []string
wait func() bool
expectErr bool
skipTest bool
}{
{
args: []string{"serve", "all", "--sqa-opt-out"},
Expand Down Expand Up @@ -116,14 +120,15 @@ func TestExecute(t *testing.T) {
{args: []string{"clients", "create", "--skip-tls-verify", "--endpoint", backend, "--id", "public-foo"}},
{args: []string{"clients", "create", "--skip-tls-verify", "--endpoint", backend, "--id", "confidential-foo", "--pgp-key", base64EncodedPGPPublicKey(t), "--grant-types", "client_credentials", "--response-types", "token"}},
{args: []string{"clients", "delete", "--skip-tls-verify", "--endpoint", backend, "public-foo"}},
{args: []string{"keys", "create", "--skip-tls-verify", "foo", "--endpoint", backend, "-a", "HS256"}},
{args: []string{"keys", "create", "--skip-tls-verify", "foo", "--endpoint", backend, "-a", "RS256"}},
{args: []string{"keys", "create", "--skip-tls-verify", "foo", "--endpoint", backend, "-a", "HS256"}, skipTest: conf.HsmEnabled()},
{args: []string{"keys", "get", "--skip-tls-verify", "--endpoint", backend, "foo"}},
// {args: []string{"keys", "rotate", "--skip-tls-verify", "--endpoint", backend, "foo"}},
{args: []string{"keys", "get", "--skip-tls-verify", "--endpoint", backend, "foo"}},
{args: []string{"keys", "delete", "--skip-tls-verify", "--endpoint", backend, "foo"}},
{args: []string{"keys", "import", "--skip-tls-verify", "--endpoint", backend, "import-1", "../test/stub/ecdh.key", "../test/stub/ecdh.pub"}},
{args: []string{"keys", "import", "--skip-tls-verify", "--endpoint", backend, "import-2", "../test/stub/rsa.key", "../test/stub/rsa.pub"}},
{args: []string{"keys", "import", "--skip-tls-verify", "--endpoint", backend, "import-2", "../test/stub/rsa.key", "../test/stub/rsa.pub"}},
{args: []string{"keys", "import", "--skip-tls-verify", "--endpoint", backend, "import-1", "../test/stub/ecdh.key", "../test/stub/ecdh.pub"}, skipTest: conf.HsmEnabled()},
{args: []string{"keys", "import", "--skip-tls-verify", "--endpoint", backend, "import-2", "../test/stub/rsa.key", "../test/stub/rsa.pub"}, skipTest: conf.HsmEnabled()},
{args: []string{"keys", "import", "--skip-tls-verify", "--endpoint", backend, "import-2", "../test/stub/rsa.key", "../test/stub/rsa.pub"}, skipTest: conf.HsmEnabled()},
{args: []string{"token", "revoke", "--skip-tls-verify", "--endpoint", frontend, "--client-secret", "foobar", "--client-id", "foobarbaz", "foo"}},
{args: []string{"token", "client", "--skip-tls-verify", "--endpoint", frontend, "--client-secret", "foobar", "--client-id", "foobarbaz"}},
{args: []string{"help", "migrate", "sql"}},
Expand All @@ -133,6 +138,10 @@ func TestExecute(t *testing.T) {
rootCmd.SetArgs(c.args)

t.Run(fmt.Sprintf("command=%v", c.args), func(t *testing.T) {
if c.skipTest {
t.Skip("Skipping test. Not applicable when Hardware Security Module is enabled")
}

if c.wait != nil {
go func() {
assert.Nil(t, rootCmd.Execute())
Expand Down
10 changes: 5 additions & 5 deletions cmd/server/helper_cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import (
)

const (
tlsKeyName = "hydra.https-tls"
TlsKeyName = "hydra.https-tls"
)

func AttachCertificate(priv *jose.JSONWebKey, cert *x509.Certificate) {
Expand All @@ -63,9 +63,9 @@ func GetOrCreateTLSCertificate(cmd *cobra.Command, d driver.Registry, iface conf
d.Logger().WithError(err).Fatalf("Unable to load HTTPS TLS Certificate")
}

_, priv, err := jwk.AsymmetricKeypair(context.Background(), d, &jwk.RS256Generator{KeyLength: 4069}, tlsKeyName)
_, priv, err := jwk.GetOrGenerateKeys(context.Background(), d, d.SoftwareKeyManager(), TlsKeyName, TlsKeyName, "RS256")
if err != nil {
d.Logger().WithError(err).Fatal("Unable to fetch HTTPS TLS key pairs")
d.Logger().WithError(err).Fatal("Unable to fetch or generate HTTPS TLS key pair")
}

if len(priv.Certificates) == 0 {
Expand All @@ -75,11 +75,11 @@ func GetOrCreateTLSCertificate(cmd *cobra.Command, d driver.Registry, iface conf
}

AttachCertificate(priv, cert)
if err := d.KeyManager().DeleteKey(context.TODO(), tlsKeyName, priv.KeyID); err != nil {
if err := d.SoftwareKeyManager().DeleteKey(context.TODO(), TlsKeyName, priv.KeyID); err != nil {
d.Logger().WithError(err).Fatal(`Could not update (delete) the self signed TLS certificate`)
}

if err := d.KeyManager().AddKey(context.TODO(), tlsKeyName, priv); err != nil {
if err := d.SoftwareKeyManager().AddKey(context.TODO(), TlsKeyName, priv); err != nil {
d.Logger().WithError(err).Fatalf(`Could not update (add) the self signed TLS certificate: %s %x %d`, cert.SignatureAlgorithm, cert.Signature, len(cert.Signature))
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
projectName: 'ORY Hydra',
projectName: 'Ory Hydra',
projectSlug: 'hydra',
newsletter:
'https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53&group[17097][8]=1',
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/.static/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@
}
},
"put": {
"description": "Use this method if you do not want to let Hydra generate the JWKs for you, but instead save your own.\n\nA JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. A JWK Set is a JSON data structure that represents a set of JWKs. A JSON Web Key is identified by its set and key id. ORY Hydra uses this functionality to store cryptographic keys used for TLS and JSON Web Tokens (such as OpenID Connect ID tokens), and allows storing user-defined keys as well.",
"description": "Use this method if you do not want to let Hydra generate the JWKs for you, but instead save your own.\n\nA JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. A JWK Set is a JSON data structure that represents a set of JWKs. A JSON Web Key is identified by its set and key id. ORY Hydra uses this functionality to store cryptographic keys used for TLS and JSON Web Tokens (such as OpenID Connect ID tokens), and allows storing user-defined keys as well. This method is not supported when Hardware Security Module is enabled.",
"consumes": ["application/json"],
"produces": ["application/json"],
"schemes": ["http", "https"],
Expand Down Expand Up @@ -577,7 +577,7 @@
}
},
"post": {
"description": "This endpoint is capable of generating JSON Web Key Sets for you. There a different strategies available, such as symmetric cryptographic keys (HS256, HS512) and asymetric cryptographic keys (RS256, ECDSA). If the specified JSON Web Key Set does not exist, it will be created.\n\nA JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. A JWK Set is a JSON data structure that represents a set of JWKs. A JSON Web Key is identified by its set and key id. ORY Hydra uses this functionality to store cryptographic keys used for TLS and JSON Web Tokens (such as OpenID Connect ID tokens), and allows storing user-defined keys as well.",
"description": "This endpoint is capable of generating JSON Web Key Sets for you. There a different strategies available, such as symmetric cryptographic keys (HS256, HS512) and asymetric cryptographic keys (RS256, ECDSA, EdDSA). When Hardware Security Module is enabled, then only RS256, ECDSA key strategies are available. If the specified JSON Web Key Set does not exist, it will be created.\n\nA JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. A JWK Set is a JSON data structure that represents a set of JWKs. A JSON Web Key is identified by its set and key id. ORY Hydra uses this functionality to store cryptographic keys used for TLS and JSON Web Tokens (such as OpenID Connect ID tokens), and allows storing user-defined keys as well.",
"consumes": ["application/json"],
"produces": ["application/json"],
"schemes": ["http", "https"],
Expand Down Expand Up @@ -716,7 +716,7 @@
}
},
"put": {
"description": "Use this method if you do not want to let Hydra generate the JWKs for you, but instead save your own.\n\nA JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. A JWK Set is a JSON data structure that represents a set of JWKs. A JSON Web Key is identified by its set and key id. ORY Hydra uses this functionality to store cryptographic keys used for TLS and JSON Web Tokens (such as OpenID Connect ID tokens), and allows storing user-defined keys as well.",
"description": "Use this method if you do not want to let Hydra generate the JWKs for you, but instead save your own.\n\nA JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. A JWK Set is a JSON data structure that represents a set of JWKs. A JSON Web Key is identified by its set and key id. ORY Hydra uses this functionality to store cryptographic keys used for TLS and JSON Web Tokens (such as OpenID Connect ID tokens), and allows storing user-defined keys as well. This method is not supported when Hardware Security Module is enabled.",
"consumes": ["application/json"],
"produces": ["application/json"],
"schemes": ["http", "https"],
Expand Down
14 changes: 11 additions & 3 deletions docs/docs/5min-tutorial.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ $ docker-compose -f quickstart.yml \
up --build
```

If you want to test Hardware Security Module add `-f quickstart-hsm.yml`. For
more information head over to [HSM support](hsm-support).

```shell script
$ docker-compose -f quickstart.yml \
-f quickstart-hsm.yml \
up --build
```

Let's confirm that everything is working by creating an OAuth 2.0 Client.

Note: The following commands run Hydra inside Docker. If you have the ORY Hydra
Expand Down Expand Up @@ -186,9 +195,8 @@ $ docker-compose -f quickstart.yml rm -f -v

### Quickstart Configuration

In this tutorial we use a simplified configuration.
You can find it in
[`contrib/quickstart/5-min/hydra.yml`](https://github.com/ory/hydra/blob/master/contrib/quickstart/5-min/hydra.yml).
In this tutorial we use a simplified configuration. You can find it in
[`contrib/quickstart/5-min/hydra.yml`](https://github.com/ory/hydra/blob/master/contrib/quickstart/5-min/hydra.yml).
The configuration gets loaded in docker-compose as specified in the
[`quickstart.yml`](https://github.com/ory/hydra/blob/master/quickstart.yml).

Expand Down
Loading