mirror of https://github.com/dexidp/dex.git
10 changed files with 327 additions and 4 deletions
@ -0,0 +1,5 @@
|
||||
*.key |
||||
*.crt |
||||
*.csr |
||||
index.* |
||||
serial* |
||||
@ -0,0 +1,62 @@
|
||||
# Running a Dex gRPC client |
||||
|
||||
Using gRPC, a client application can directly call methods on a server application as if it was a local object. The schema for Dex's gRPC API calls is defined in [`api/api.proto`][api-proto]. [`client.go`][client] is an example client program that makes a bunch of API calls to the dex server. For further details on the Dex API refer [`Documentation/api.md`][api-docs]. |
||||
|
||||
## Generating Credentials |
||||
|
||||
Before running the client or the server, TLS credentials have to be setup for secure communication. Run the `cred-gen` script to create TLS credentials for running this example. This script generates a `ca.crt`, `server.crt`, `server.key`, `client.crt`, and `client.key`. |
||||
|
||||
``` |
||||
# Used to set certificate subject alt names. |
||||
export SAN=IP.1:127.0.0.1 |
||||
|
||||
# Run the script |
||||
./examples/grpc-client/cert-gen |
||||
``` |
||||
To verify that the server and client certificates were signed by the CA, run the following commands: |
||||
|
||||
``` |
||||
openssl verify -CAfile ca.crt server.crt |
||||
openssl verify -CAfile ca.crt client.crt |
||||
``` |
||||
|
||||
## Running the Dex server |
||||
|
||||
To expose the gRPC service, the gRPC option must be enabled via the dex config file as shown below. |
||||
|
||||
```yaml |
||||
# Enables the gRPC API. |
||||
grpc: |
||||
addr: 127.0.0.1:5557 |
||||
tlsCert: server.crt |
||||
tlsKey: server.key |
||||
|
||||
``` |
||||
Start an instance of the dex server with an in-memory data store: |
||||
|
||||
``` |
||||
./bin/dex serve examples/grpc-client/config.yaml |
||||
``` |
||||
|
||||
## Running the Dex client |
||||
|
||||
Finally run the Dex client providing the CA certificate, client certificate and client key as arguments. |
||||
|
||||
``` |
||||
./bin/grpc-client -ca-crt=ca.crt -client-crt=client.crt -client-key=client.key |
||||
``` |
||||
Running the gRPC client will cause the following API calls to be made to the server |
||||
1. CreatePassword |
||||
2. ListPasswords |
||||
3. DeletePassword |
||||
|
||||
## Cleaning up |
||||
|
||||
Run the following command to destroy all the credentials files that were created by the `cert-gen` script: |
||||
|
||||
``` |
||||
./examples/grpc-client/cert-destory |
||||
``` |
||||
[api-proto]: ../../api/api.proto |
||||
[client]: client.go |
||||
[api-docs]: ../../Documentation/api.md |
||||
@ -0,0 +1,4 @@
|
||||
#!/bin/bash |
||||
|
||||
rm -f ca.key ca.crt server.key server.csr server.crt client.key client.csr client.crt index.* serial* |
||||
rm -rf certs crl newcerts |
||||
@ -0,0 +1,35 @@
|
||||
#!/bin/bash |
||||
|
||||
if [ -z $SAN ] |
||||
then echo "Set SAN with a DNS or IP(e.g. export SAN=IP.1:127.0.0.1,IP.2:172.18.0.2)." |
||||
exit 1 |
||||
fi |
||||
|
||||
echo "Creating CA, server cert/key, and client cert/key..." |
||||
|
||||
# Creating basic files/directories |
||||
mkdir -p {certs,crl,newcerts} |
||||
touch index.txt |
||||
echo 1000 > serial |
||||
|
||||
# CA private key (unencrypted) |
||||
openssl genrsa -out ca.key 4096 |
||||
# Certificate Authority (self-signed certificate) |
||||
openssl req -config examples/grpc-client/openssl.conf -new -x509 -days 3650 -sha256 -key ca.key -extensions v3_ca -out ca.crt -subj "/CN=fake-ca" |
||||
|
||||
# Server private key (unencrypted) |
||||
openssl genrsa -out server.key 2048 |
||||
# Server certificate signing request (CSR) |
||||
openssl req -config examples/grpc-client/openssl.conf -new -sha256 -key server.key -out server.csr -subj "/CN=fake-server" |
||||
# Certificate Authority signs CSR to grant a certificate |
||||
openssl ca -batch -config examples/grpc-client/openssl.conf -extensions server_cert -days 365 -notext -md sha256 -in server.csr -out server.crt -cert ca.crt -keyfile ca.key |
||||
|
||||
# Client private key (unencrypted) |
||||
openssl genrsa -out client.key 2048 |
||||
# Signed client certificate signing request (CSR) |
||||
openssl req -config examples/grpc-client/openssl.conf -new -sha256 -key client.key -out client.csr -subj "/CN=fake-client" |
||||
# Certificate Authority signs CSR to grant a certificate |
||||
openssl ca -batch -config examples/grpc-client/openssl.conf -extensions usr_cert -days 365 -notext -md sha256 -in client.csr -out client.crt -cert ca.crt -keyfile ca.key |
||||
|
||||
# Remove CSR's |
||||
rm *.csr |
||||
@ -0,0 +1,106 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"context" |
||||
"crypto/tls" |
||||
"crypto/x509" |
||||
"flag" |
||||
"fmt" |
||||
"io/ioutil" |
||||
"log" |
||||
|
||||
"github.com/coreos/dex/api" |
||||
"google.golang.org/grpc" |
||||
"google.golang.org/grpc/credentials" |
||||
) |
||||
|
||||
func newDexClient(hostAndPort, caPath, clientCrt, clientKey string) (api.DexClient, error) { |
||||
cPool := x509.NewCertPool() |
||||
caCert, err := ioutil.ReadFile(caPath) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("invalid CA crt file: %s", caPath) |
||||
} |
||||
if cPool.AppendCertsFromPEM(caCert) != true { |
||||
return nil, fmt.Errorf("failed to parse CA crt") |
||||
} |
||||
|
||||
clientCert, err := tls.LoadX509KeyPair(clientCrt, clientKey) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("invalid client crt file: %s", caPath) |
||||
} |
||||
|
||||
clientTLSConfig := &tls.Config{ |
||||
RootCAs: cPool, |
||||
Certificates: []tls.Certificate{clientCert}, |
||||
} |
||||
creds := credentials.NewTLS(clientTLSConfig) |
||||
|
||||
conn, err := grpc.Dial(hostAndPort, grpc.WithTransportCredentials(creds)) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("dail: %v", err) |
||||
} |
||||
return api.NewDexClient(conn), nil |
||||
} |
||||
|
||||
func main() { |
||||
caCrt := flag.String("ca-crt", "", "CA certificate") |
||||
clientCrt := flag.String("client-crt", "", "Client certificate") |
||||
clientKey := flag.String("client-key", "", "Client key") |
||||
flag.Parse() |
||||
|
||||
if *clientCrt == "" || *caCrt == "" || *clientKey == "" { |
||||
log.Fatal("Please provide CA & client certificates and client key. Usage: ./client -ca_crt=<path ca.crt> -client_crt=<path client.crt> -client_key=<path client key>") |
||||
} |
||||
|
||||
client, err := newDexClient("127.0.0.1:5557", *caCrt, *clientCrt, *clientKey) |
||||
if err != nil { |
||||
log.Fatalf("failed creating dex client: %v ", err) |
||||
} |
||||
|
||||
p := api.Password{ |
||||
Email: "test@example.com", |
||||
// bcrypt hash of the value "test1" with cost 10
|
||||
Hash: []byte("$2a$10$XVMN/Fid.Ks4CXgzo8fpR.iU1khOMsP5g9xQeXuBm1wXjRX8pjUtO"), |
||||
Username: "test", |
||||
UserId: "test", |
||||
} |
||||
|
||||
createReq := &api.CreatePasswordReq{ |
||||
Password: &p, |
||||
} |
||||
|
||||
// Create password.
|
||||
if resp, err := client.CreatePassword(context.TODO(), createReq); err != nil || resp.AlreadyExists { |
||||
if resp.AlreadyExists { |
||||
log.Fatalf("Password %s already exists", createReq.Password.Email) |
||||
} |
||||
log.Fatalf("failed to create password: %v", err) |
||||
} else { |
||||
log.Printf("Created password with email %s", createReq.Password.Email) |
||||
} |
||||
|
||||
// List all passwords.
|
||||
resp, err := client.ListPasswords(context.TODO(), &api.ListPasswordReq{}) |
||||
if err != nil { |
||||
log.Fatalf("failed to list password: %v", err) |
||||
} |
||||
|
||||
log.Print("Listing Passwords:\n") |
||||
for _, pass := range resp.Passwords { |
||||
log.Printf("%+v", pass) |
||||
} |
||||
|
||||
deleteReq := &api.DeletePasswordReq{ |
||||
Email: p.Email, |
||||
} |
||||
|
||||
// Delete password with email = test@example.com.
|
||||
if resp, err := client.DeletePassword(context.TODO(), deleteReq); err != nil || resp.NotFound { |
||||
if resp.NotFound { |
||||
log.Fatalf("Password %s not found", deleteReq.Email) |
||||
} |
||||
log.Fatalf("failed to delete password: %v", err) |
||||
} else { |
||||
log.Printf("Deleted password with email %s", deleteReq.Email) |
||||
} |
||||
} |
||||
@ -0,0 +1,24 @@
|
||||
issuer: http://127.0.0.1:5556/dex |
||||
|
||||
storage: |
||||
type: sqlite3 |
||||
config: |
||||
file: examples/dex.db |
||||
|
||||
# Configuration for the HTTP endpoints. |
||||
web: |
||||
http: 0.0.0.0:5556 |
||||
|
||||
grpc: |
||||
addr: 127.0.0.1:5557 |
||||
tlsCert: server.crt |
||||
tlsKey: server.key |
||||
|
||||
connectors: |
||||
- type: mockCallback |
||||
id: mock |
||||
name: Example |
||||
|
||||
# Let dex keep a list of passwords which can be used to login to dex. |
||||
enablePasswordDB: true |
||||
|
||||
@ -0,0 +1,82 @@
|
||||
# OpenSSL configuration file. |
||||
# Adapted from https://github.com/coreos/matchbox/blob/master/examples/etc/matchbox/openssl.conf |
||||
|
||||
# default environment variable values |
||||
SAN = |
||||
|
||||
[ ca ] |
||||
# `man ca` |
||||
default_ca = CA_default |
||||
|
||||
[ CA_default ] |
||||
# Directory and file locations. |
||||
dir = . |
||||
certs = $dir/certs |
||||
crl_dir = $dir/crl |
||||
new_certs_dir = $dir/newcerts |
||||
database = $dir/index.txt |
||||
serial = $dir/serial |
||||
# certificate revocation lists. |
||||
crlnumber = $dir/crlnumber |
||||
crl = $dir/crl/intermediate-ca.crl |
||||
crl_extensions = crl_ext |
||||
default_crl_days = 30 |
||||
default_md = sha256 |
||||
|
||||
name_opt = ca_default |
||||
cert_opt = ca_default |
||||
default_days = 375 |
||||
preserve = no |
||||
policy = policy_loose |
||||
|
||||
[ policy_loose ] |
||||
# Allow the CA to sign a range of certificates. |
||||
countryName = optional |
||||
stateOrProvinceName = optional |
||||
localityName = optional |
||||
organizationName = optional |
||||
organizationalUnitName = optional |
||||
commonName = supplied |
||||
emailAddress = optional |
||||
|
||||
[ req ] |
||||
# `man req` |
||||
default_bits = 4096 |
||||
distinguished_name = req_distinguished_name |
||||
string_mask = utf8only |
||||
default_md = sha256 |
||||
|
||||
[ req_distinguished_name ] |
||||
countryName = Country Name (2 letter code) |
||||
stateOrProvinceName = State or Province Name |
||||
localityName = Locality Name |
||||
0.organizationName = Organization Name |
||||
organizationalUnitName = Organizational Unit Name |
||||
commonName = Common Name |
||||
|
||||
# Certificate extensions (`man x509v3_config`) |
||||
|
||||
[ v3_ca ] |
||||
subjectKeyIdentifier = hash |
||||
authorityKeyIdentifier = keyid:always,issuer |
||||
basicConstraints = critical, CA:true, pathlen:0 |
||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign |
||||
|
||||
[ usr_cert ] |
||||
basicConstraints = CA:FALSE |
||||
nsCertType = client |
||||
nsComment = "OpenSSL Generated Client Certificate" |
||||
subjectKeyIdentifier = hash |
||||
authorityKeyIdentifier = keyid,issuer |
||||
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment |
||||
extendedKeyUsage = clientAuth |
||||
|
||||
[ server_cert ] |
||||
basicConstraints = CA:FALSE |
||||
nsCertType = server |
||||
nsComment = "OpenSSL Generated Server Certificate" |
||||
subjectKeyIdentifier = hash |
||||
authorityKeyIdentifier = keyid,issuer:always |
||||
keyUsage = critical, digitalSignature, keyEncipherment |
||||
extendedKeyUsage = serverAuth |
||||
subjectAltName = $ENV::SAN |
||||
Loading…
Reference in new issue