From 1471893c2fb193eec89415fe9f8a2d22ff12843b Mon Sep 17 00:00:00 2001 From: Aleksander Cynarski Date: Thu, 15 Oct 2020 23:08:04 +0200 Subject: [PATCH] Implementacja DEX --- README.md | 19 +++++++- dex/config-dev.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++ dex/config-ldap.yaml | 55 +++++++++++++++++++++ dex/dex.db | 0 docker-compose.yml | 51 ++++++++------------ krakend/krakend.json | 22 ++++++++- ldap/config-ldap.ldif | 44 +++++++++++++++++ 7 files changed, 266 insertions(+), 34 deletions(-) create mode 100644 dex/config-dev.yaml create mode 100644 dex/config-ldap.yaml create mode 100755 dex/dex.db create mode 100644 ldap/config-ldap.ldif diff --git a/README.md b/README.md index 45d38d5..b17c327 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,32 @@ W tym etapie wprowadzimy nowy request zabezpieczony tokenem JWT: ```mermaid sequenceDiagram Użytkownik->>KrakenD: /jwt_access
[Authorizaion: Bearer token] - KrakenD->>Hydra: .well-known/jwks.json - Hydra-->>KrakenD: jwk + KrakenD->>DEX: dex/keys + DEX-->>KrakenD: jwk KrakenD-->>KrakenD: validator
[issuer] KrakenD->>Backend: /users/1.json Backend-->>KrakenD: response_0 KrakenD->>+Użytkownik: Response ``` +Dodatkowy scope `groups` + +```mermaid +sequenceDiagram + Użytkownik->>KrakenD: /jwt_access_admin
[Authorizaion: Bearer token] + KrakenD->>DEX: dex/keys + DEX-->>KrakenD: jwk + KrakenD-->>KrakenD: validator
[issuer, groups: admins] + KrakenD->>Backend: /users/1.json + Backend-->>KrakenD: response_0 + KrakenD->>+Użytkownik: Response +``` + + Flow jest typowo testowy, na razie nie ma revoke jwt, a samo pobranie tokenu należy zrobić za pomocą pliku `Makefile`. + Przykład wykorzystania KrakenD do zabezpieczenia bakendu za pomocą JWT: [![asciicast](https://asciinema.org/a/Py3dbR2m5Jt3FdhGI7eINtpdu.png)](https://asciinema.org/a/Py3dbR2m5Jt3FdhGI7eINtpdu) diff --git a/dex/config-dev.yaml b/dex/config-dev.yaml new file mode 100644 index 0000000..dd61c83 --- /dev/null +++ b/dex/config-dev.yaml @@ -0,0 +1,109 @@ +# The base path of dex and the external name of the OpenID Connect service. +# This is the canonical URL that all clients MUST use to refer to dex. If a +# path is provided, dex's HTTP service will listen at a non-root URL. +issuer: http://127.0.0.1:5556/dex + +# The storage configuration determines where dex stores its state. Supported +# options include SQL flavors and Kubernetes third party resources. +# +# See the storage document at Documentation/storage.md for further information. +storage: + type: postgres + config: + host: postgresd + port: 5432 + database: dex + user: dex + password: postgres + ssl: + mode: disable + + +# Configuration for the HTTP endpoints. +web: + http: 0.0.0.0:5556 + # Uncomment for HTTPS options. + # https: 127.0.0.1:5554 + # tlsCert: /etc/dex/tls.crt + # tlsKey: /etc/dex/tls.key + +# Configuration for telemetry +telemetry: + http: 0.0.0.0:5558 + +# Uncomment this block to enable the gRPC API. This values MUST be different +# from the HTTP endpoints. +# grpc: +# addr: 127.0.0.1:5557 +# tlsCert: examples/grpc-client/server.crt +# tlsKey: examples/grpc-client/server.key +# tlsClientCA: /etc/dex/client.crt + +# Uncomment this block to enable configuration for the expiration time durations. +# expiry: +# deviceRequests: "5m" +# signingKeys: "6h" +# idTokens: "24h" + +# Options for controlling the logger. +# logger: +# level: "debug" +# format: "text" # can also be "json" + +# Default values shown below +# oauth2: + # use ["code", "token", "id_token"] to enable implicit flow for web-only clients +# responseTypes: [ "code" ] # also allowed are "token" and "id_token" + # By default, Dex will ask for approval to share data with application + # (approval for sharing data from connected IdP to Dex is separate process on IdP) +# skipApprovalScreen: false + # If only one authentication method is enabled, the default behavior is to + # go directly to it. For connected IdPs, this redirects the browser away + # from application to upstream provider such as the Google login page +# alwaysShowLoginScreen: false + # Uncommend the passwordConnector to use a specific connector for password grants +# passwordConnector: local + +# Instead of reading from an external storage, use this list of clients. +# +# If this option isn't chosen clients may be added through the gRPC API. +staticClients: +- id: example-app + redirectURIs: + - 'http://127.0.0.1:5555/callback' + name: 'Example App' + secret: ZXhhbXBsZS1hcHAtc2VjcmV0 +# - id: example-device-client +# redirectURIs: +# - /device/callback +# name: 'Static Client for Device Flow' +# public: true +connectors: +- type: mockCallback + id: mock + name: Example +# - type: google +# id: google +# name: Google +# config: +# issuer: https://accounts.google.com +# # Connector config values starting with a "$" will read from the environment. +# clientID: $GOOGLE_CLIENT_ID +# clientSecret: $GOOGLE_CLIENT_SECRET +# redirectURI: http://127.0.0.1:5556/dex/callback +# hostedDomains: +# - $GOOGLE_HOSTED_DOMAIN + +# Let dex keep a list of passwords which can be used to login to dex. +enablePasswordDB: true + +# A static list of passwords to login the end user. By identifying here, dex +# won't look in its underlying storage for passwords. +# +# If this option isn't chosen users may be added through the gRPC API. +staticPasswords: +- email: "admin@example.com" + # bcrypt hash of the string "password" + hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" + username: "admin" + userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" diff --git a/dex/config-ldap.yaml b/dex/config-ldap.yaml new file mode 100644 index 0000000..bd2f8f2 --- /dev/null +++ b/dex/config-ldap.yaml @@ -0,0 +1,55 @@ +issuer: http://127.0.0.1:5556/dex + +storage: + type: postgres + config: + host: postgresd + port: 5432 + database: dex + user: dex + password: postgres + ssl: + mode: disable + +connectors: +- type: ldap + name: OpenLDAP + id: ldap + config: + host: ldap:389 + + insecureNoSSL: true + + bindDN: cn=admin,dc=example,dc=org + bindPW: admin + + usernamePrompt: Email Address + + userSearch: + baseDN: ou=People,dc=example,dc=org + filter: "(objectClass=person)" + username: mail + idAttr: DN + emailAttr: mail + nameAttr: cn + + groupSearch: + baseDN: ou=Groups,dc=example,dc=org + filter: "(objectClass=groupOfNames)" + + userMatchers: + - userAttr: DN + groupAttr: member + + nameAttr: cn + +web: + http: 0.0.0.0:5556 + +staticClients: +- id: example-app + redirectURIs: + - 'http://127.0.0.1:5555/callback' + name: 'Example App' + secret: ZXhhbXBsZS1hcHAtc2VjcmV0 + diff --git a/dex/dex.db b/dex/dex.db new file mode 100755 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml index 0834401..56abad0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,45 +14,36 @@ services: ports: - "8000:8080" - hydra-migrate: - image: oryd/hydra:v1.8.5 - environment: - - DSN=postgres://hydra:secret@postgresd:5432/hydra?sslmode=disable&max_conns=20&max_idle_conns=4 - command: - migrate sql -e --yes - restart: on-failure + ldap: + image: osixia/openldap:1.4.0 + command: ["--copy-service"] + volumes: + - ./ldap/config-ldap.ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom/config-ldap.ldif + ports: + - 389:389 + - 636:636 + postgresd: image: postgres:9.6 ports: - "5432:5432" environment: - - POSTGRES_USER=hydra - - POSTGRES_PASSWORD=secret - - POSTGRES_DB=hydra + - POSTGRES_USER=dex + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=dex - hydra: - image: oryd/hydra:v1.8.5 + dex: + image: quay.io/dexidp/dex:latest + command: ["serve", "/config/config-ldap.yaml"] + volumes: + - ./dex:/config ports: - - "4444:4444" # Public port - - "4445:4445" # Admin port - - "5555:5555" # Port for hydra token user - command: - serve all --dangerous-force-http - env_file: ./.env - restart: unless-stopped + - 5556:5556 + - 5558:5558 depends_on: - - hydra-migrate - - consent: - #image: oryd/hydra-login-consent-node:latest - image: paramah/consent:latest - environment: - - HYDRA_ADMIN_URL=http://hydra:4445 - - BASE_URL=http://consent.service.consul:3000 - ports: - - "3000:3000" - restart: unless-stopped + - postgresd + - ldap kraken: image: devopsfaith/krakend:config-watcher diff --git a/krakend/krakend.json b/krakend/krakend.json index 5b3a095..30fcf6d 100644 --- a/krakend/krakend.json +++ b/krakend/krakend.json @@ -84,8 +84,26 @@ "extra_config": { "github.com/devopsfaith/krakend-jose/validator": { "alg": "RS256", - "issuer": "http://127.0.0.1:4444/", - "jwk-url": "http://hydra:4444/.well-known/jwks.json", + "issuer": "http://127.0.0.1:5556/dex", + "jwk-url": "http://dex:5556/dex/keys", + "disable_jwk_security": true + } + } + }, + { + "endpoint": "/jwt_access_admin", + "backend": [ + { + "url_pattern": "/users/1.json" + } + ], + "extra_config": { + "github.com/devopsfaith/krakend-jose/validator": { + "alg": "RS256", + "issuer": "http://127.0.0.1:5556/dex", + "jwk-url": "http://dex:5556/dex/keys", + "roles_key": "groups", + "roles": ["admins"], "disable_jwk_security": true } } diff --git a/ldap/config-ldap.ldif b/ldap/config-ldap.ldif new file mode 100644 index 0000000..8840bf8 --- /dev/null +++ b/ldap/config-ldap.ldif @@ -0,0 +1,44 @@ +# Already included in default config of Docker image osixia/openldap:1.4.0. +# +# dn: dc=example,dc=org +# objectClass: dcObject +# objectClass: organization +# o: Example Company +# dc: example + +dn: ou=People,dc=example,dc=org +objectClass: organizationalUnit +ou: People + +dn: cn=jane,ou=People,dc=example,dc=org +objectClass: person +objectClass: inetOrgPerson +sn: doe +cn: jane +mail: janedoe@example.com +userpassword: foo + +dn: cn=john,ou=People,dc=example,dc=org +objectClass: person +objectClass: inetOrgPerson +sn: doe +cn: john +mail: johndoe@example.com +userpassword: bar + +# Group definitions. + +dn: ou=Groups,dc=example,dc=org +objectClass: organizationalUnit +ou: Groups + +dn: cn=admins,ou=Groups,dc=example,dc=org +objectClass: groupOfNames +cn: admins +member: cn=john,ou=People,dc=example,dc=org +member: cn=jane,ou=People,dc=example,dc=org + +dn: cn=developers,ou=Groups,dc=example,dc=org +objectClass: groupOfNames +cn: developers +member: cn=jane,ou=People,dc=example,dc=org