Fix dependency and linter errors.
This commit is contained in:
parent
0eb0c3a21b
commit
852f4ed564
10 changed files with 338 additions and 143 deletions
154
Gopkg.lock
generated
154
Gopkg.lock
generated
|
@ -35,6 +35,14 @@
|
||||||
revision = "b90dc15cfd220ecf8bbc9043ecb928cef381f011"
|
revision = "b90dc15cfd220ecf8bbc9043ecb928cef381f011"
|
||||||
version = "v0.3.4"
|
version = "v0.3.4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda"
|
||||||
|
name = "github.com/ghodss/yaml"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:81fda4d18a16651bf92245ce5d6178cdd99f918db30ae9794732655f0686e895"
|
digest = "1:81fda4d18a16651bf92245ce5d6178cdd99f918db30ae9794732655f0686e895"
|
||||||
|
@ -43,6 +51,17 @@
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "0ebf7795c516423a110473652e9ba3a59a504863"
|
revision = "0ebf7795c516423a110473652e9ba3a59a504863"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:b402bb9a24d108a9405a6f34675091b036c8b056aac843bf6ef2389a65c5cf48"
|
||||||
|
name = "github.com/gogo/protobuf"
|
||||||
|
packages = [
|
||||||
|
"proto",
|
||||||
|
"sortkeys",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "4cbf7e384e768b4e01799441fdf2a706a5635ae7"
|
||||||
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "travis-1.9"
|
branch = "travis-1.9"
|
||||||
digest = "1:e8f5d9c09a7209c740e769713376abda388c41b777ba8e9ed52767e21acf379f"
|
digest = "1:e8f5d9c09a7209c740e769713376abda388c41b777ba8e9ed52767e21acf379f"
|
||||||
|
@ -54,6 +73,28 @@
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "883fe33ffc4344bad1ecd881f61afd5ec5d80e0a"
|
revision = "883fe33ffc4344bad1ecd881f61afd5ec5d80e0a"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:0f1010da61da43ef23bae5c43a619abda82e04f409ec642e6bdeee0d7736530d"
|
||||||
|
name = "github.com/google/certificate-transparency-go"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"asn1",
|
||||||
|
"tls",
|
||||||
|
"x509",
|
||||||
|
"x509/pkix",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "3629d6846518309d22c16fee15d1007262a459d2"
|
||||||
|
version = "v1.0.21"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:3ee90c0d94da31b442dde97c99635aaafec68d0b8a3c12ee2075c6bdabeec6bb"
|
||||||
|
name = "github.com/google/gofuzz"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:750e747d0aad97b79f4a4e00034bae415c2ea793fd9e61438d966ee9c79579bf"
|
digest = "1:750e747d0aad97b79f4a4e00034bae415c2ea793fd9e61438d966ee9c79579bf"
|
||||||
|
@ -70,6 +111,14 @@
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "1003c8bd00dc2869cb5ca5282e6ce33834fed514"
|
revision = "1003c8bd00dc2869cb5ca5282e6ce33834fed514"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:3e551bbb3a7c0ab2a2bf4660e7fcad16db089fdcfbb44b0199e62838038623ea"
|
||||||
|
name = "github.com/json-iterator/go"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
|
||||||
|
version = "v1.1.5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:e51f40f0c19b39c1825eadd07d5c0a98a2ad5942b166d9fc4f54750ce9a04810"
|
digest = "1:e51f40f0c19b39c1825eadd07d5c0a98a2ad5942b166d9fc4f54750ce9a04810"
|
||||||
|
@ -125,6 +174,22 @@
|
||||||
revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c"
|
revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c"
|
||||||
version = "v0.0.4"
|
version = "v0.0.4"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
|
||||||
|
name = "github.com/modern-go/concurrent"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
|
||||||
|
version = "1.0.3"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855"
|
||||||
|
name = "github.com/modern-go/reflect2"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
|
||||||
|
version = "1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:266d082179f3a29a4bdcf1dcc49d4a304f5c7107e65bd22d1fecacf45f1ac348"
|
digest = "1:266d082179f3a29a4bdcf1dcc49d4a304f5c7107e65bd22d1fecacf45f1ac348"
|
||||||
name = "github.com/newrelic/go-agent"
|
name = "github.com/newrelic/go-agent"
|
||||||
|
@ -212,7 +277,7 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:4c9e30abfe7c119eb4d40287f6c23f854f3ad71c69206d8dc6402e1fef14ac88"
|
digest = "1:17d4424defbc718315d61e296841867ff76b3e03a941b41fdddbae11a7d47746"
|
||||||
name = "github.com/smallstep/cli"
|
name = "github.com/smallstep/cli"
|
||||||
packages = [
|
packages = [
|
||||||
"command",
|
"command",
|
||||||
|
@ -226,6 +291,8 @@
|
||||||
"jose",
|
"jose",
|
||||||
"pkg/blackfriday",
|
"pkg/blackfriday",
|
||||||
"pkg/x509",
|
"pkg/x509",
|
||||||
|
"token",
|
||||||
|
"token/provision",
|
||||||
"ui",
|
"ui",
|
||||||
"usage",
|
"usage",
|
||||||
"utils",
|
"utils",
|
||||||
|
@ -333,6 +400,14 @@
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "63abe20a23e29e80bbef8089bd3dee3ac25e5306"
|
revision = "63abe20a23e29e80bbef8089bd3dee3ac25e5306"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a"
|
||||||
|
name = "gopkg.in/inf.v0"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
|
||||||
|
version = "v0.9.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:7fbe10f3790dc4e6296c7c844c5a9b35513e5521c29c47e10ba99cd2956a2719"
|
digest = "1:7fbe10f3790dc4e6296c7c844c5a9b35513e5521c29c47e10ba99cd2956a2719"
|
||||||
name = "gopkg.in/square/go-jose.v2"
|
name = "gopkg.in/square/go-jose.v2"
|
||||||
|
@ -354,20 +429,90 @@
|
||||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
version = "v2.2.1"
|
version = "v2.2.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:767b6c0b2c1d9487ee50cb8df1d0fdebf06ac0b19b723f6489d388e7b47c962d"
|
||||||
|
name = "k8s.io/api"
|
||||||
|
packages = [
|
||||||
|
"admission/v1beta1",
|
||||||
|
"authentication/v1",
|
||||||
|
"core/v1",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "de494049e22a9ccf748c5bbda7492f42f344d0cd"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:5eb353533eaebdfec2392210ab218a389965ba5d4dc02b4aef87b9549e5d0f84"
|
||||||
|
name = "k8s.io/apimachinery"
|
||||||
|
packages = [
|
||||||
|
"pkg/api/resource",
|
||||||
|
"pkg/apis/meta/v1",
|
||||||
|
"pkg/apis/meta/v1/unstructured",
|
||||||
|
"pkg/conversion",
|
||||||
|
"pkg/conversion/queryparams",
|
||||||
|
"pkg/fields",
|
||||||
|
"pkg/labels",
|
||||||
|
"pkg/runtime",
|
||||||
|
"pkg/runtime/schema",
|
||||||
|
"pkg/runtime/serializer",
|
||||||
|
"pkg/runtime/serializer/json",
|
||||||
|
"pkg/runtime/serializer/protobuf",
|
||||||
|
"pkg/runtime/serializer/recognizer",
|
||||||
|
"pkg/runtime/serializer/versioning",
|
||||||
|
"pkg/selection",
|
||||||
|
"pkg/types",
|
||||||
|
"pkg/util/errors",
|
||||||
|
"pkg/util/framer",
|
||||||
|
"pkg/util/intstr",
|
||||||
|
"pkg/util/json",
|
||||||
|
"pkg/util/naming",
|
||||||
|
"pkg/util/net",
|
||||||
|
"pkg/util/runtime",
|
||||||
|
"pkg/util/sets",
|
||||||
|
"pkg/util/validation",
|
||||||
|
"pkg/util/validation/field",
|
||||||
|
"pkg/util/yaml",
|
||||||
|
"pkg/watch",
|
||||||
|
"third_party/forked/golang/reflect",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "4b3b852955ebe47857fcf134b531b23dd8f3e793"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:72fd56341405f53c745377e0ebc4abeff87f1a048e0eea6568a20212650f5a82"
|
||||||
|
name = "k8s.io/klog"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "71442cd4037d612096940ceb0f3fec3f7fff66e0"
|
||||||
|
version = "v0.2.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:7719608fe0b52a4ece56c2dde37bedd95b938677d1ab0f84b8a7852e4c59f849"
|
||||||
|
name = "sigs.k8s.io/yaml"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
input-imports = [
|
input-imports = [
|
||||||
"github.com/alecthomas/gometalinter",
|
"github.com/alecthomas/gometalinter",
|
||||||
"github.com/client9/misspell/cmd/misspell",
|
"github.com/client9/misspell/cmd/misspell",
|
||||||
|
"github.com/ghodss/yaml",
|
||||||
"github.com/go-chi/chi",
|
"github.com/go-chi/chi",
|
||||||
"github.com/golang/lint/golint",
|
"github.com/golang/lint/golint",
|
||||||
|
"github.com/google/certificate-transparency-go",
|
||||||
|
"github.com/google/certificate-transparency-go/x509",
|
||||||
"github.com/gordonklaus/ineffassign",
|
"github.com/gordonklaus/ineffassign",
|
||||||
"github.com/newrelic/go-agent",
|
"github.com/newrelic/go-agent",
|
||||||
"github.com/pkg/errors",
|
"github.com/pkg/errors",
|
||||||
"github.com/rs/xid",
|
"github.com/rs/xid",
|
||||||
"github.com/sirupsen/logrus",
|
"github.com/sirupsen/logrus",
|
||||||
"github.com/smallstep/assert",
|
"github.com/smallstep/assert",
|
||||||
|
"github.com/smallstep/cli/config",
|
||||||
"github.com/smallstep/cli/crypto/keys",
|
"github.com/smallstep/cli/crypto/keys",
|
||||||
"github.com/smallstep/cli/crypto/pemutil",
|
"github.com/smallstep/cli/crypto/pemutil",
|
||||||
"github.com/smallstep/cli/crypto/randutil",
|
"github.com/smallstep/cli/crypto/randutil",
|
||||||
|
@ -376,12 +521,19 @@
|
||||||
"github.com/smallstep/cli/errs",
|
"github.com/smallstep/cli/errs",
|
||||||
"github.com/smallstep/cli/jose",
|
"github.com/smallstep/cli/jose",
|
||||||
"github.com/smallstep/cli/pkg/x509",
|
"github.com/smallstep/cli/pkg/x509",
|
||||||
|
"github.com/smallstep/cli/token",
|
||||||
|
"github.com/smallstep/cli/token/provision",
|
||||||
"github.com/smallstep/cli/usage",
|
"github.com/smallstep/cli/usage",
|
||||||
"github.com/tsenart/deadcode",
|
"github.com/tsenart/deadcode",
|
||||||
"github.com/urfave/cli",
|
"github.com/urfave/cli",
|
||||||
"golang.org/x/net/http2",
|
"golang.org/x/net/http2",
|
||||||
"gopkg.in/square/go-jose.v2",
|
"gopkg.in/square/go-jose.v2",
|
||||||
"gopkg.in/square/go-jose.v2/jwt",
|
"gopkg.in/square/go-jose.v2/jwt",
|
||||||
|
"k8s.io/api/admission/v1beta1",
|
||||||
|
"k8s.io/api/core/v1",
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer",
|
||||||
]
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -113,12 +113,3 @@ func NewInClusterK8sClient() (Client, error) {
|
||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInsecureK8sClient creates an insecure k8s client which is suitable
|
|
||||||
// to connect kubernetes api behind proxy
|
|
||||||
func NewInsecureK8sClient(apiURL string) Client {
|
|
||||||
return &k8sClient{
|
|
||||||
host: apiURL,
|
|
||||||
httpClient: http.DefaultClient,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,8 +3,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/json"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -18,8 +18,8 @@ import (
|
||||||
"github.com/smallstep/certificates/ca"
|
"github.com/smallstep/certificates/ca"
|
||||||
"github.com/smallstep/cli/crypto/pemutil"
|
"github.com/smallstep/cli/crypto/pemutil"
|
||||||
"k8s.io/api/admission/v1beta1"
|
"k8s.io/api/admission/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
)
|
)
|
||||||
|
@ -30,8 +30,8 @@ var (
|
||||||
deserializer = codecs.UniversalDeserializer()
|
deserializer = codecs.UniversalDeserializer()
|
||||||
// GetRootCAPath() is broken; points to secrets not certs. So
|
// GetRootCAPath() is broken; points to secrets not certs. So
|
||||||
// we'll hard code instead for now.
|
// we'll hard code instead for now.
|
||||||
//rootCAPath = pki.GetRootCAPath()
|
//rootCAPath = pki.GetRootCAPath()
|
||||||
rootCAPath = "/home/step/.step/certs/root_ca.crt"
|
rootCAPath = "/home/step/.step/certs/root_ca.crt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -45,23 +45,23 @@ const (
|
||||||
|
|
||||||
// Config options for the autocert admission controller.
|
// Config options for the autocert admission controller.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
LogFormat string `yaml:"logFormat"`
|
LogFormat string `yaml:"logFormat"`
|
||||||
CaUrl string `yaml:"caUrl"`
|
CaURL string `yaml:"caUrl"`
|
||||||
CertLifetime string `yaml:"certLifetime"`
|
CertLifetime string `yaml:"certLifetime"`
|
||||||
Bootstrapper corev1.Container `yaml:"bootstrapper"`
|
Bootstrapper corev1.Container `yaml:"bootstrapper"`
|
||||||
Renewer corev1.Container `yaml:"renewer"`
|
Renewer corev1.Container `yaml:"renewer"`
|
||||||
CertsVolume corev1.Volume `yaml:"certsVolume"`
|
CertsVolume corev1.Volume `yaml:"certsVolume"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC6902 JSONPatch Operation
|
// PatchOperation represents a RFC6902 JSONPatch Operation
|
||||||
type PatchOperation struct {
|
type PatchOperation struct {
|
||||||
Op string `json:"op"`
|
Op string `json:"op"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Value interface{} `json:"value,omitempty"`
|
Value interface{} `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC6901 JSONPath Escaping -- https://tools.ietf.org/html/rfc6901
|
// RFC6901 JSONPath Escaping -- https://tools.ietf.org/html/rfc6901
|
||||||
func escapeJsonPath(path string) string {
|
func escapeJSONPath(path string) string {
|
||||||
// Replace`~` with `~0` then `/` with `~1`. Note that the order
|
// Replace`~` with `~0` then `/` with `~1`. Note that the order
|
||||||
// matters otherwise we'll turn a `/` into a `~/`.
|
// matters otherwise we'll turn a `/` into a `~/`.
|
||||||
path = strings.Replace(path, "~", "~0", -1)
|
path = strings.Replace(path, "~", "~0", -1)
|
||||||
|
@ -79,7 +79,7 @@ func loadConfig(file string) (*Config, error) {
|
||||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &cfg, nil
|
return &cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,19 +88,19 @@ func loadConfig(file string) (*Config, error) {
|
||||||
// A goroutine is scheduled to cleanup the secret after the token expires. The secret
|
// A goroutine is scheduled to cleanup the secret after the token expires. The secret
|
||||||
// is also labelled for easy identification and manual cleanup.
|
// is also labelled for easy identification and manual cleanup.
|
||||||
func createTokenSecret(prefix, namespace, token string) (string, error) {
|
func createTokenSecret(prefix, namespace, token string) (string, error) {
|
||||||
secret := corev1.Secret {
|
secret := corev1.Secret{
|
||||||
TypeMeta: metav1.TypeMeta {
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Secret",
|
Kind: "Secret",
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta {
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
GenerateName: prefix,
|
GenerateName: prefix,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: map[string]string {
|
Labels: map[string]string{
|
||||||
tokenSecretLabel: "true",
|
tokenSecretLabel: "true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StringData: map[string]string {
|
StringData: map[string]string{
|
||||||
tokenSecretKey: token,
|
tokenSecretKey: token,
|
||||||
},
|
},
|
||||||
Type: corev1.SecretTypeOpaque,
|
Type: corev1.SecretTypeOpaque,
|
||||||
|
@ -162,7 +162,7 @@ func createTokenSecret(prefix, namespace, token string) (string, error) {
|
||||||
time.Sleep(tokenLifetime)
|
time.Sleep(tokenLifetime)
|
||||||
req, err := client.DeleteRequest(fmt.Sprintf("api/v1/namespaces/%s/secrets/%s", namespace, created.Name))
|
req, err := client.DeleteRequest(fmt.Sprintf("api/v1/namespaces/%s/secrets/%s", namespace, created.Name))
|
||||||
ctxLog := log.WithFields(log.Fields{
|
ctxLog := log.WithFields(log.Fields{
|
||||||
"name": created.Name,
|
"name": created.Name,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -176,7 +176,7 @@ func createTokenSecret(prefix, namespace, token string) (string, error) {
|
||||||
}
|
}
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||||
ctxLog.WithFields(log.Fields{
|
ctxLog.WithFields(log.Fields{
|
||||||
"status": resp.Status,
|
"status": resp.Status,
|
||||||
"statusCode": resp.StatusCode,
|
"statusCode": resp.StatusCode,
|
||||||
}).Error("Error deleting expired boostrap token secret")
|
}).Error("Error deleting expired boostrap token secret")
|
||||||
return
|
return
|
||||||
|
@ -206,109 +206,109 @@ func mkBootstrapper(config *Config, commonName string, namespace string, provisi
|
||||||
sum := sha256.Sum256(crt.Raw)
|
sum := sha256.Sum256(crt.Raw)
|
||||||
fingerprint := strings.ToLower(hex.EncodeToString(sum[:]))
|
fingerprint := strings.ToLower(hex.EncodeToString(sum[:]))
|
||||||
|
|
||||||
secretName, err := createTokenSecret(commonName + "-", namespace, token)
|
secretName, err := createTokenSecret(commonName+"-", namespace, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return b, errors.Wrap(err, "create token secret")
|
return b, errors.Wrap(err, "create token secret")
|
||||||
}
|
}
|
||||||
log.Infof("Secret name is: %s", secretName)
|
log.Infof("Secret name is: %s", secretName)
|
||||||
|
|
||||||
b.Env = append(b.Env, corev1.EnvVar {
|
b.Env = append(b.Env, corev1.EnvVar{
|
||||||
Name: "COMMON_NAME",
|
Name: "COMMON_NAME",
|
||||||
Value: commonName,
|
Value: commonName,
|
||||||
})
|
})
|
||||||
b.Env = append(b.Env, corev1.EnvVar {
|
b.Env = append(b.Env, corev1.EnvVar{
|
||||||
Name: "STEP_TOKEN",
|
Name: "STEP_TOKEN",
|
||||||
ValueFrom: &corev1.EnvVarSource {
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
SecretKeyRef: &corev1.SecretKeySelector {
|
SecretKeyRef: &corev1.SecretKeySelector{
|
||||||
LocalObjectReference: corev1.LocalObjectReference {
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
Name: secretName,
|
Name: secretName,
|
||||||
},
|
},
|
||||||
Key: tokenSecretKey,
|
Key: tokenSecretKey,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
b.Env = append(b.Env, corev1.EnvVar {
|
b.Env = append(b.Env, corev1.EnvVar{
|
||||||
Name: "STEP_CA_URL",
|
Name: "STEP_CA_URL",
|
||||||
Value: config.CaUrl,
|
Value: config.CaURL,
|
||||||
})
|
})
|
||||||
b.Env = append(b.Env, corev1.EnvVar {
|
b.Env = append(b.Env, corev1.EnvVar{
|
||||||
Name: "STEP_FINGERPRINT",
|
Name: "STEP_FINGERPRINT",
|
||||||
Value: fingerprint,
|
Value: fingerprint,
|
||||||
})
|
})
|
||||||
b.Env = append(b.Env, corev1.EnvVar {
|
b.Env = append(b.Env, corev1.EnvVar{
|
||||||
Name: "STEP_NOT_AFTER",
|
Name: "STEP_NOT_AFTER",
|
||||||
Value: config.CertLifetime,
|
Value: config.CertLifetime,
|
||||||
})
|
})
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mkRenewer generates a new renewer based on the template provided in Config.
|
// mkRenewer generates a new renewer based on the template provided in Config.
|
||||||
func mkRenewer(config *Config) (corev1.Container) {
|
func mkRenewer(config *Config) corev1.Container {
|
||||||
r := config.Renewer
|
r := config.Renewer
|
||||||
r.Env = append(r.Env, corev1.EnvVar {
|
r.Env = append(r.Env, corev1.EnvVar{
|
||||||
Name: "STEP_CA_URL",
|
Name: "STEP_CA_URL",
|
||||||
Value: config.CaUrl,
|
Value: config.CaURL,
|
||||||
})
|
})
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func addContainers(existing, new []corev1.Container, path string) (ops []PatchOperation) {
|
func addContainers(existing, new []corev1.Container, path string) (ops []PatchOperation) {
|
||||||
if len(existing) == 0 {
|
|
||||||
return []PatchOperation {
|
|
||||||
PatchOperation {
|
|
||||||
Op: "add",
|
|
||||||
Path: path,
|
|
||||||
Value: new,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, add := range new {
|
|
||||||
ops = append(ops, PatchOperation {
|
|
||||||
Op: "add",
|
|
||||||
Path: path + "/-",
|
|
||||||
Value: add,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return ops
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func addVolumes(existing, new []corev1.Volume, path string) (ops []PatchOperation) {
|
|
||||||
if len(existing) == 0 {
|
if len(existing) == 0 {
|
||||||
return []PatchOperation{
|
return []PatchOperation{
|
||||||
PatchOperation {
|
{
|
||||||
Op: "add",
|
Op: "add",
|
||||||
Path: path,
|
Path: path,
|
||||||
Value: new,
|
Value: new,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for _, add := range new {
|
|
||||||
ops = append(ops, PatchOperation {
|
|
||||||
Op: "add",
|
|
||||||
Path: path + "/-",
|
|
||||||
Value: add,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return ops
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, add := range new {
|
||||||
|
ops = append(ops, PatchOperation{
|
||||||
|
Op: "add",
|
||||||
|
Path: path + "/-",
|
||||||
|
Value: add,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ops
|
||||||
|
}
|
||||||
|
|
||||||
|
func addVolumes(existing, new []corev1.Volume, path string) (ops []PatchOperation) {
|
||||||
|
if len(existing) == 0 {
|
||||||
|
return []PatchOperation{
|
||||||
|
{
|
||||||
|
Op: "add",
|
||||||
|
Path: path,
|
||||||
|
Value: new,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, add := range new {
|
||||||
|
ops = append(ops, PatchOperation{
|
||||||
|
Op: "add",
|
||||||
|
Path: path + "/-",
|
||||||
|
Value: add,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ops
|
||||||
}
|
}
|
||||||
|
|
||||||
func addCertsVolumeMount(volumeName string, containers []corev1.Container) (ops []PatchOperation) {
|
func addCertsVolumeMount(volumeName string, containers []corev1.Container) (ops []PatchOperation) {
|
||||||
volumeMount := corev1.VolumeMount {
|
volumeMount := corev1.VolumeMount{
|
||||||
Name: volumeName,
|
Name: volumeName,
|
||||||
MountPath: volumeMountPath,
|
MountPath: volumeMountPath,
|
||||||
ReadOnly: true,
|
ReadOnly: true,
|
||||||
}
|
}
|
||||||
for i, container := range containers {
|
for i, container := range containers {
|
||||||
if len(container.VolumeMounts) == 0 {
|
if len(container.VolumeMounts) == 0 {
|
||||||
ops = append(ops, PatchOperation {
|
ops = append(ops, PatchOperation{
|
||||||
Op: "add",
|
Op: "add",
|
||||||
Path: fmt.Sprintf("/spec/containers/%v/volumeMounts", i),
|
Path: fmt.Sprintf("/spec/containers/%v/volumeMounts", i),
|
||||||
Value: []corev1.VolumeMount{volumeMount},
|
Value: []corev1.VolumeMount{volumeMount},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ops = append(ops, PatchOperation {
|
ops = append(ops, PatchOperation{
|
||||||
Op: "add",
|
Op: "add",
|
||||||
Path: fmt.Sprintf("/spec/containers/%v/volumeMounts/-", i),
|
Path: fmt.Sprintf("/spec/containers/%v/volumeMounts/-", i),
|
||||||
Value: volumeMount,
|
Value: volumeMount,
|
||||||
|
@ -321,7 +321,7 @@ func addCertsVolumeMount(volumeName string, containers []corev1.Container) (ops
|
||||||
func addAnnotations(existing, new map[string]string) (ops []PatchOperation) {
|
func addAnnotations(existing, new map[string]string) (ops []PatchOperation) {
|
||||||
if len(existing) == 0 {
|
if len(existing) == 0 {
|
||||||
return []PatchOperation{
|
return []PatchOperation{
|
||||||
PatchOperation {
|
{
|
||||||
Op: "add",
|
Op: "add",
|
||||||
Path: "/metadata/annotations",
|
Path: "/metadata/annotations",
|
||||||
Value: new,
|
Value: new,
|
||||||
|
@ -330,15 +330,15 @@ func addAnnotations(existing, new map[string]string) (ops []PatchOperation) {
|
||||||
}
|
}
|
||||||
for k, v := range new {
|
for k, v := range new {
|
||||||
if existing[k] == "" {
|
if existing[k] == "" {
|
||||||
ops = append(ops, PatchOperation {
|
ops = append(ops, PatchOperation{
|
||||||
Op: "add",
|
Op: "add",
|
||||||
Path: "/metadata/annotations/" + escapeJsonPath(k),
|
Path: "/metadata/annotations/" + escapeJSONPath(k),
|
||||||
Value: v,
|
Value: v,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ops = append(ops, PatchOperation {
|
ops = append(ops, PatchOperation{
|
||||||
Op: "replace",
|
Op: "replace",
|
||||||
Path: "/metadata/annotations/" + escapeJsonPath(k),
|
Path: "/metadata/annotations/" + escapeJSONPath(k),
|
||||||
Value: v,
|
Value: v,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -355,7 +355,7 @@ func addAnnotations(existing, new map[string]string) (ops []PatchOperation) {
|
||||||
// - Annotate the pod to indicate that it's been processed by this controller
|
// - Annotate the pod to indicate that it's been processed by this controller
|
||||||
// The result is a list of serialized JSONPatch objects (or an error).
|
// The result is a list of serialized JSONPatch objects (or an error).
|
||||||
func patch(pod *corev1.Pod, namespace string, config *Config, provisioner Provisioner) ([]byte, error) {
|
func patch(pod *corev1.Pod, namespace string, config *Config, provisioner Provisioner) ([]byte, error) {
|
||||||
var ops[] PatchOperation
|
var ops []PatchOperation
|
||||||
|
|
||||||
commonName := pod.ObjectMeta.GetAnnotations()[admissionWebhookAnnotationKey]
|
commonName := pod.ObjectMeta.GetAnnotations()[admissionWebhookAnnotationKey]
|
||||||
renewer := mkRenewer(config)
|
renewer := mkRenewer(config)
|
||||||
|
@ -386,9 +386,9 @@ func shouldMutate(metadata *metav1.ObjectMeta) bool {
|
||||||
// mutated already (status key isn't set).
|
// mutated already (status key isn't set).
|
||||||
if annotations[admissionWebhookAnnotationKey] == "" || annotations[admissionWebhookStatusKey] == "injected" {
|
if annotations[admissionWebhookAnnotationKey] == "" || annotations[admissionWebhookStatusKey] == "injected" {
|
||||||
return false
|
return false
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutate takes an `AdmissionReview`, determines whether it is subject to mutation, and returns
|
// mutate takes an `AdmissionReview`, determines whether it is subject to mutation, and returns
|
||||||
|
@ -400,27 +400,27 @@ func mutate(review *v1beta1.AdmissionReview, config *Config, provisioner Provisi
|
||||||
var pod corev1.Pod
|
var pod corev1.Pod
|
||||||
if err := json.Unmarshal(request.Object.Raw, &pod); err != nil {
|
if err := json.Unmarshal(request.Object.Raw, &pod); err != nil {
|
||||||
ctxLog.WithField("error", err).Error("Error unmarshalling pod")
|
ctxLog.WithField("error", err).Error("Error unmarshalling pod")
|
||||||
return &v1beta1.AdmissionResponse {
|
return &v1beta1.AdmissionResponse{
|
||||||
Allowed: false,
|
Allowed: false,
|
||||||
UID: request.UID,
|
UID: request.UID,
|
||||||
Result: &metav1.Status {
|
Result: &metav1.Status{
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxLog = ctxLog.WithFields(log.Fields{
|
ctxLog = ctxLog.WithFields(log.Fields{
|
||||||
"kind": request.Kind,
|
"kind": request.Kind,
|
||||||
"operation": request.Operation,
|
"operation": request.Operation,
|
||||||
"name": pod.Name,
|
"name": pod.Name,
|
||||||
"generateName": pod.GenerateName,
|
"generateName": pod.GenerateName,
|
||||||
"namespace": request.Namespace,
|
"namespace": request.Namespace,
|
||||||
"user": request.UserInfo,
|
"user": request.UserInfo,
|
||||||
})
|
})
|
||||||
|
|
||||||
if !shouldMutate(&pod.ObjectMeta) {
|
if !shouldMutate(&pod.ObjectMeta) {
|
||||||
ctxLog.WithField("annotations", pod.Annotations).Info("Skipping mutation")
|
ctxLog.WithField("annotations", pod.Annotations).Info("Skipping mutation")
|
||||||
return &v1beta1.AdmissionResponse {
|
return &v1beta1.AdmissionResponse{
|
||||||
Allowed: true,
|
Allowed: true,
|
||||||
UID: request.UID,
|
UID: request.UID,
|
||||||
}
|
}
|
||||||
|
@ -429,20 +429,20 @@ func mutate(review *v1beta1.AdmissionReview, config *Config, provisioner Provisi
|
||||||
patchBytes, err := patch(&pod, request.Namespace, config, provisioner)
|
patchBytes, err := patch(&pod, request.Namespace, config, provisioner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctxLog.WithField("error", err).Error("Error generating patch")
|
ctxLog.WithField("error", err).Error("Error generating patch")
|
||||||
return &v1beta1.AdmissionResponse {
|
return &v1beta1.AdmissionResponse{
|
||||||
Allowed: false,
|
Allowed: false,
|
||||||
UID: request.UID,
|
UID: request.UID,
|
||||||
Result: &metav1.Status {
|
Result: &metav1.Status{
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxLog.WithField("patch", string(patchBytes)).Info("Generated patch")
|
ctxLog.WithField("patch", string(patchBytes)).Info("Generated patch")
|
||||||
return &v1beta1.AdmissionResponse {
|
return &v1beta1.AdmissionResponse{
|
||||||
Allowed: true,
|
Allowed: true,
|
||||||
Patch: patchBytes,
|
Patch: patchBytes,
|
||||||
UID: request.UID,
|
UID: request.UID,
|
||||||
PatchType: func() *v1beta1.PatchType {
|
PatchType: func() *v1beta1.PatchType {
|
||||||
pt := v1beta1.PatchTypeJSONPatch
|
pt := v1beta1.PatchTypeJSONPatch
|
||||||
return &pt
|
return &pt
|
||||||
|
@ -477,17 +477,17 @@ func main() {
|
||||||
provisionerKid := os.Getenv("PROVISIONER_KID")
|
provisionerKid := os.Getenv("PROVISIONER_KID")
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"provisionerName": provisionerName,
|
"provisionerName": provisionerName,
|
||||||
"provisionerKid": provisionerKid,
|
"provisionerKid": provisionerKid,
|
||||||
}).Info("Loaded provisioner configuration")
|
}).Info("Loaded provisioner configuration")
|
||||||
|
|
||||||
provisioner, err := NewProvisioner(provisionerName, provisionerKid, config.CaUrl, rootCAPath, provisionerPasswordFile)
|
provisioner, err := NewProvisioner(provisionerName, provisionerKid, config.CaURL, rootCAPath, provisionerPasswordFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error loading provisioner: %v", err)
|
log.Errorf("Error loading provisioner: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"name": provisioner.Name(),
|
"name": provisioner.Name(),
|
||||||
"kid": provisioner.Kid(),
|
"kid": provisioner.Kid(),
|
||||||
}).Info("Loaded provisioner")
|
}).Info("Loaded provisioner")
|
||||||
|
|
||||||
namespace := os.Getenv("NAMESPACE")
|
namespace := os.Getenv("NAMESPACE")
|
||||||
|
@ -519,10 +519,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
var name string
|
var name string
|
||||||
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
||||||
name = r.TLS.PeerCertificates[0].Subject.CommonName
|
name = r.TLS.PeerCertificates[0].Subject.CommonName
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if r.URL.Path != "/mutate" {
|
if r.URL.Path != "/mutate" {
|
||||||
|
@ -554,12 +554,12 @@ func main() {
|
||||||
review := v1beta1.AdmissionReview{}
|
review := v1beta1.AdmissionReview{}
|
||||||
if _, _, err := deserializer.Decode(body, nil, &review); err != nil {
|
if _, _, err := deserializer.Decode(body, nil, &review); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"body": body,
|
"body": body,
|
||||||
"error": err,
|
"error": err,
|
||||||
}).Error("Can't decode body")
|
}).Error("Can't decode body")
|
||||||
response = &v1beta1.AdmissionResponse {
|
response = &v1beta1.AdmissionResponse{
|
||||||
Allowed: false,
|
Allowed: false,
|
||||||
Result: &metav1.Status {
|
Result: &metav1.Status{
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -567,23 +567,23 @@ func main() {
|
||||||
response = mutate(&review, config, provisioner)
|
response = mutate(&review, config, provisioner)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := json.Marshal(v1beta1.AdmissionReview {
|
resp, err := json.Marshal(v1beta1.AdmissionReview{
|
||||||
Response: response,
|
Response: response,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"uid": review.Request.UID,
|
"uid": review.Request.UID,
|
||||||
"error": err,
|
"error": err,
|
||||||
}).Info("Marshal error")
|
}).Info("Marshal error")
|
||||||
http.Error(w, fmt.Sprintf("Marshal Error: %v", err), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("Marshal Error: %v", err), http.StatusInternalServerError)
|
||||||
} else {
|
} else {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"uid": review.Request.UID,
|
"uid": review.Request.UID,
|
||||||
"response": string(resp),
|
"response": string(resp),
|
||||||
}).Info("Returning review")
|
}).Info("Returning review")
|
||||||
if _, err := w.Write(resp); err != nil {
|
if _, err := w.Write(resp); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"uid": review.Request.UID,
|
"uid": review.Request.UID,
|
||||||
"error": err,
|
"error": err,
|
||||||
}).Info("Write error")
|
}).Info("Write error")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,13 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/cli/crypto/pki"
|
"github.com/smallstep/certificates/authority"
|
||||||
|
"github.com/smallstep/certificates/ca"
|
||||||
|
"github.com/smallstep/cli/config"
|
||||||
"github.com/smallstep/cli/crypto/randutil"
|
"github.com/smallstep/cli/crypto/randutil"
|
||||||
"github.com/smallstep/cli/jose"
|
"github.com/smallstep/cli/jose"
|
||||||
"github.com/smallstep/cli/token"
|
"github.com/smallstep/cli/token"
|
||||||
|
@ -17,6 +20,8 @@ const (
|
||||||
tokenLifetime = 5 * time.Minute
|
tokenLifetime = 5 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Provisioner is an authorized entity that can sign tokens necessary for
|
||||||
|
// signature requests.
|
||||||
type Provisioner interface {
|
type Provisioner interface {
|
||||||
Name() string
|
Name() string
|
||||||
Kid() string
|
Kid() string
|
||||||
|
@ -26,7 +31,7 @@ type Provisioner interface {
|
||||||
type provisioner struct {
|
type provisioner struct {
|
||||||
name string
|
name string
|
||||||
kid string
|
kid string
|
||||||
caUrl string
|
caURL string
|
||||||
caRoot string
|
caRoot string
|
||||||
jwk *jose.JSONWebKey
|
jwk *jose.JSONWebKey
|
||||||
tokenLifetime time.Duration
|
tokenLifetime time.Duration
|
||||||
|
@ -52,13 +57,13 @@ func (p *provisioner) Token(subject string) (string, error) {
|
||||||
|
|
||||||
notBefore := time.Now()
|
notBefore := time.Now()
|
||||||
notAfter := notBefore.Add(tokenLifetime)
|
notAfter := notBefore.Add(tokenLifetime)
|
||||||
signUrl := fmt.Sprintf("%v/1.0/sign", p.caUrl)
|
signURL := fmt.Sprintf("%v/1.0/sign", p.caURL)
|
||||||
|
|
||||||
tokOptions := []token.Options{
|
tokOptions := []token.Options{
|
||||||
token.WithJWTID(jwtID),
|
token.WithJWTID(jwtID),
|
||||||
token.WithKid(p.kid),
|
token.WithKid(p.kid),
|
||||||
token.WithIssuer(p.name),
|
token.WithIssuer(p.name),
|
||||||
token.WithAudience(signUrl),
|
token.WithAudience(signURL),
|
||||||
token.WithValidity(notBefore, notAfter),
|
token.WithValidity(notBefore, notAfter),
|
||||||
token.WithRootCA(p.caRoot),
|
token.WithRootCA(p.caRoot),
|
||||||
}
|
}
|
||||||
|
@ -86,20 +91,20 @@ func decryptProvisionerJWK(encryptedKey, passFile string) (*jose.JSONWebKey, err
|
||||||
|
|
||||||
// loadProvisionerJWKByKid retrieves a provisioner key from the CA by key ID and
|
// loadProvisionerJWKByKid retrieves a provisioner key from the CA by key ID and
|
||||||
// decrypts it using the specified password file.
|
// decrypts it using the specified password file.
|
||||||
func loadProvisionerJWKByKid(kid, caUrl, caRoot, passFile string) (*jose.JSONWebKey, error) {
|
func loadProvisionerJWKByKid(kid, caURL, caRoot, passFile string) (*jose.JSONWebKey, error) {
|
||||||
encrypted, err := pki.GetProvisionerKey(caUrl, caRoot, kid)
|
encrypted, err := getProvisionerKey(caURL, caRoot, kid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return decryptProvisionerJWK(encrypted, passFile)
|
return decryptProvisionerJWK(encrypted, passFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadProvisionerJWKByName retrieves the list of provisioners and encrypted key then
|
// loadProvisionerJWKByName retrieves the list of provisioners and encrypted key then
|
||||||
// returns the key of the first provisioner with a matching name that can be successfully
|
// returns the key of the first provisioner with a matching name that can be successfully
|
||||||
// decrypted with the specified password file.
|
// decrypted with the specified password file.
|
||||||
func loadProvisionerJWKByName(name, caUrl, caRoot, passFile string) (key *jose.JSONWebKey, err error) {
|
func loadProvisionerJWKByName(name, caURL, caRoot, passFile string) (key *jose.JSONWebKey, err error) {
|
||||||
provisioners, err := pki.GetProvisioners(caUrl, caRoot)
|
provisioners, err := getProvisioners(caURL, caRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "error getting the provisioners")
|
err = errors.Wrap(err, "error getting the provisioners")
|
||||||
return
|
return
|
||||||
|
@ -113,20 +118,20 @@ func loadProvisionerJWKByName(name, caUrl, caRoot, passFile string) (key *jose.J
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New(fmt.Sprintf("provisioner '%s' not found (or your password is wrong)", name))
|
return nil, errors.Errorf("provisioner '%s' not found (or your password is wrong)", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProvisioner loads and decrypts key material from the CA for the named
|
// NewProvisioner loads and decrypts key material from the CA for the named
|
||||||
// provisioner. The key identified by `kid` will be used if specified. If `kid`
|
// provisioner. The key identified by `kid` will be used if specified. If `kid`
|
||||||
// is the empty string we'll use the first key for the named provisioner that
|
// is the empty string we'll use the first key for the named provisioner that
|
||||||
// decrypts using `passFile`.
|
// decrypts using `passFile`.
|
||||||
func NewProvisioner(name, kid, caUrl, caRoot, passFile string) (Provisioner, error) {
|
func NewProvisioner(name, kid, caURL, caRoot, passFile string) (Provisioner, error) {
|
||||||
var jwk *jose.JSONWebKey
|
var jwk *jose.JSONWebKey
|
||||||
var err error
|
var err error
|
||||||
if kid != "" {
|
if kid != "" {
|
||||||
jwk, err = loadProvisionerJWKByKid(kid, caUrl, caRoot, passFile)
|
jwk, err = loadProvisionerJWKByKid(kid, caURL, caRoot, passFile)
|
||||||
} else {
|
} else {
|
||||||
jwk, err = loadProvisionerJWKByName(name, caUrl, caRoot, passFile)
|
jwk, err = loadProvisionerJWKByName(name, caURL, caRoot, passFile)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -135,9 +140,56 @@ func NewProvisioner(name, kid, caUrl, caRoot, passFile string) (Provisioner, err
|
||||||
return &provisioner{
|
return &provisioner{
|
||||||
name: name,
|
name: name,
|
||||||
kid: jwk.KeyID,
|
kid: jwk.KeyID,
|
||||||
caUrl: caUrl,
|
caURL: caURL,
|
||||||
caRoot: caRoot,
|
caRoot: caRoot,
|
||||||
jwk: jwk,
|
jwk: jwk,
|
||||||
tokenLifetime: tokenLifetime,
|
tokenLifetime: tokenLifetime,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRootCAPath returns the path where the root CA is stored based on the
|
||||||
|
// STEPPATH environment variable.
|
||||||
|
func getRootCAPath() string {
|
||||||
|
return filepath.Join(config.StepPath(), "certs", "root_ca.crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getProvisioners returns the map of provisioners on the given CA.
|
||||||
|
func getProvisioners(caURL, rootFile string) ([]*authority.Provisioner, error) {
|
||||||
|
if len(rootFile) == 0 {
|
||||||
|
rootFile = getRootCAPath()
|
||||||
|
}
|
||||||
|
client, err := ca.NewClient(caURL, ca.WithRootFile(rootFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cursor := ""
|
||||||
|
provisioners := []*authority.Provisioner{}
|
||||||
|
for {
|
||||||
|
resp, err := client.Provisioners(ca.WithProvisionerCursor(cursor), ca.WithProvisionerLimit(100))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
provisioners = append(provisioners, resp.Provisioners...)
|
||||||
|
if resp.NextCursor == "" {
|
||||||
|
return provisioners, nil
|
||||||
|
}
|
||||||
|
cursor = resp.NextCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getProvisionerKey returns the encrypted provisioner key with the for the
|
||||||
|
// given kid.
|
||||||
|
func getProvisionerKey(caURL, rootFile, kid string) (string, error) {
|
||||||
|
if len(rootFile) == 0 {
|
||||||
|
rootFile = getRootCAPath()
|
||||||
|
}
|
||||||
|
client, err := ca.NewClient(caURL, ca.WithRootFile(rootFile))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
resp, err := client.ProvisionerKey(kid)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return resp.Key, nil
|
||||||
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (r *rotator) loadCertificate(certFile, keyFile string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
r.certificate = &c
|
r.certificate = &c
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +87,8 @@ func main() {
|
||||||
ClientCAs: roots,
|
ClientCAs: roots,
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
||||||
PreferServerCipherSuites: true,
|
PreferServerCipherSuites: true,
|
||||||
CipherSuites: []uint16{
|
CipherSuites: []uint16{
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
},
|
},
|
||||||
|
@ -119,7 +119,7 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error loading certificate and key", err)
|
log.Println("Error loading certificate and key", err)
|
||||||
}
|
}
|
||||||
case <- done:
|
case <-done:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ func main() {
|
||||||
defer close(done)
|
defer close(done)
|
||||||
|
|
||||||
log.Println("Listening no :443")
|
log.Println("Listening no :443")
|
||||||
|
|
||||||
// Start serving HTTPS
|
// Start serving HTTPS
|
||||||
err = srv.ListenAndServeTLS("", "")
|
err = srv.ListenAndServeTLS("", "")
|
||||||
if err != nil {
|
if err != nil {
|
Loading…
Reference in a new issue