rename pcf to cf maintaining backwards compat (#7346)
This commit is contained in:
parent
9816963355
commit
64ecf46fb6
|
@ -23,10 +23,10 @@ import (
|
|||
"github.com/hashicorp/vault/command/agent/auth/aws"
|
||||
"github.com/hashicorp/vault/command/agent/auth/azure"
|
||||
"github.com/hashicorp/vault/command/agent/auth/cert"
|
||||
"github.com/hashicorp/vault/command/agent/auth/cf"
|
||||
"github.com/hashicorp/vault/command/agent/auth/gcp"
|
||||
"github.com/hashicorp/vault/command/agent/auth/jwt"
|
||||
"github.com/hashicorp/vault/command/agent/auth/kubernetes"
|
||||
"github.com/hashicorp/vault/command/agent/auth/pcf"
|
||||
"github.com/hashicorp/vault/command/agent/cache"
|
||||
"github.com/hashicorp/vault/command/agent/config"
|
||||
"github.com/hashicorp/vault/command/agent/sink"
|
||||
|
@ -342,6 +342,8 @@ func (c *AgentCommand) Run(args []string) int {
|
|||
method, err = azure.NewAzureAuthMethod(authConfig)
|
||||
case "cert":
|
||||
method, err = cert.NewCertAuthMethod(authConfig)
|
||||
case "cf":
|
||||
method, err = cf.NewCFAuthMethod(authConfig)
|
||||
case "gcp":
|
||||
method, err = gcp.NewGCPAuthMethod(authConfig)
|
||||
case "jwt":
|
||||
|
@ -350,8 +352,8 @@ func (c *AgentCommand) Run(args []string) int {
|
|||
method, err = kubernetes.NewKubernetesAuthMethod(authConfig)
|
||||
case "approle":
|
||||
method, err = approle.NewApproleAuthMethod(authConfig)
|
||||
case "pcf":
|
||||
method, err = pcf.NewPCFAuthMethod(authConfig)
|
||||
case "pcf": // Deprecated.
|
||||
method, err = cf.NewCFAuthMethod(authConfig)
|
||||
default:
|
||||
c.UI.Error(fmt.Sprintf("Unknown auth method %q", config.AutoAuth.Method.Type))
|
||||
return 1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -8,25 +8,25 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
pcf "github.com/hashicorp/vault-plugin-auth-pcf"
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/signatures"
|
||||
cf "github.com/hashicorp/vault-plugin-auth-cf"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/signatures"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/command/agent/auth"
|
||||
)
|
||||
|
||||
type pcfMethod struct {
|
||||
type cfMethod struct {
|
||||
mountPath string
|
||||
roleName string
|
||||
}
|
||||
|
||||
func NewPCFAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) {
|
||||
func NewCFAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) {
|
||||
if conf == nil {
|
||||
return nil, errors.New("empty config")
|
||||
}
|
||||
if conf.Config == nil {
|
||||
return nil, errors.New("empty config data")
|
||||
}
|
||||
a := &pcfMethod{
|
||||
a := &cfMethod{
|
||||
mountPath: conf.MountPath,
|
||||
}
|
||||
if raw, ok := conf.Config["role"]; ok {
|
||||
|
@ -41,18 +41,18 @@ func NewPCFAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) {
|
|||
return a, nil
|
||||
}
|
||||
|
||||
func (p *pcfMethod) Authenticate(ctx context.Context, client *api.Client) (string, map[string]interface{}, error) {
|
||||
pathToClientCert := os.Getenv(pcf.EnvVarInstanceCertificate)
|
||||
func (p *cfMethod) Authenticate(ctx context.Context, client *api.Client) (string, map[string]interface{}, error) {
|
||||
pathToClientCert := os.Getenv(cf.EnvVarInstanceCertificate)
|
||||
if pathToClientCert == "" {
|
||||
return "", nil, fmt.Errorf("missing %q value", pcf.EnvVarInstanceCertificate)
|
||||
return "", nil, fmt.Errorf("missing %q value", cf.EnvVarInstanceCertificate)
|
||||
}
|
||||
certBytes, err := ioutil.ReadFile(pathToClientCert)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
pathToClientKey := os.Getenv(pcf.EnvVarInstanceKey)
|
||||
pathToClientKey := os.Getenv(cf.EnvVarInstanceKey)
|
||||
if pathToClientKey == "" {
|
||||
return "", nil, fmt.Errorf("missing %q value", pcf.EnvVarInstanceKey)
|
||||
return "", nil, fmt.Errorf("missing %q value", cf.EnvVarInstanceKey)
|
||||
}
|
||||
signingTime := time.Now().UTC()
|
||||
signatureData := &signatures.SignatureData{
|
||||
|
@ -73,10 +73,10 @@ func (p *pcfMethod) Authenticate(ctx context.Context, client *api.Client) (strin
|
|||
return fmt.Sprintf("%s/login", p.mountPath), data, nil
|
||||
}
|
||||
|
||||
func (p *pcfMethod) NewCreds() chan struct{} {
|
||||
func (p *cfMethod) NewCreds() chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pcfMethod) CredSuccess() {}
|
||||
func (p *cfMethod) CredSuccess() {}
|
||||
|
||||
func (p *pcfMethod) Shutdown() {}
|
||||
func (p *cfMethod) Shutdown() {}
|
|
@ -9,12 +9,12 @@ import (
|
|||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
credPCF "github.com/hashicorp/vault-plugin-auth-pcf"
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/testing/certificates"
|
||||
pcfAPI "github.com/hashicorp/vault-plugin-auth-pcf/testing/pcf"
|
||||
credCF "github.com/hashicorp/vault-plugin-auth-cf"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/testing/certificates"
|
||||
cfAPI "github.com/hashicorp/vault-plugin-auth-cf/testing/cf"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/command/agent/auth"
|
||||
agentpcf "github.com/hashicorp/vault/command/agent/auth/pcf"
|
||||
agentcf "github.com/hashicorp/vault/command/agent/auth/cf"
|
||||
"github.com/hashicorp/vault/command/agent/sink"
|
||||
"github.com/hashicorp/vault/command/agent/sink/file"
|
||||
vaulthttp "github.com/hashicorp/vault/http"
|
||||
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/hashicorp/vault/vault"
|
||||
)
|
||||
|
||||
func TestPCFEndToEnd(t *testing.T) {
|
||||
func TestCFEndToEnd(t *testing.T) {
|
||||
logger := logging.NewVaultLogger(hclog.Trace)
|
||||
|
||||
coreConfig := &vault.CoreConfig{
|
||||
|
@ -31,7 +31,7 @@ func TestPCFEndToEnd(t *testing.T) {
|
|||
DisableCache: true,
|
||||
Logger: log.NewNullLogger(),
|
||||
CredentialBackends: map[string]logical.Factory{
|
||||
"pcf": credPCF.Factory,
|
||||
"cf": credCF.Factory,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -45,51 +45,51 @@ func TestPCFEndToEnd(t *testing.T) {
|
|||
cores := cluster.Cores
|
||||
vault.TestWaitActive(t, cores[0].Core)
|
||||
client := cores[0].Client
|
||||
if err := client.Sys().EnableAuthWithOptions("pcf", &api.EnableAuthOptions{
|
||||
Type: "pcf",
|
||||
if err := client.Sys().EnableAuthWithOptions("cf", &api.EnableAuthOptions{
|
||||
Type: "cf",
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testIPAddress := "127.0.0.1"
|
||||
|
||||
// Generate some valid certs that look like the ones we get from PCF.
|
||||
testPCFCerts, err := certificates.Generate(pcfAPI.FoundServiceGUID, pcfAPI.FoundOrgGUID, pcfAPI.FoundSpaceGUID, pcfAPI.FoundAppGUID, testIPAddress)
|
||||
// Generate some valid certs that look like the ones we get from CF.
|
||||
testCFCerts, err := certificates.Generate(cfAPI.FoundServiceGUID, cfAPI.FoundOrgGUID, cfAPI.FoundSpaceGUID, cfAPI.FoundAppGUID, testIPAddress)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := testPCFCerts.Close(); err != nil {
|
||||
if err := testCFCerts.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Start a mock server representing their API.
|
||||
mockPCFAPI := pcfAPI.MockServer(false)
|
||||
defer mockPCFAPI.Close()
|
||||
mockCFAPI := cfAPI.MockServer(false)
|
||||
defer mockCFAPI.Close()
|
||||
|
||||
// Configure a CA certificate like a Vault operator would in setting up PCF.
|
||||
if _, err := client.Logical().Write("auth/pcf/config", map[string]interface{}{
|
||||
"identity_ca_certificates": testPCFCerts.CACertificate,
|
||||
"pcf_api_addr": mockPCFAPI.URL,
|
||||
"pcf_username": pcfAPI.AuthUsername,
|
||||
"pcf_password": pcfAPI.AuthPassword,
|
||||
// Configure a CA certificate like a Vault operator would in setting up CF.
|
||||
if _, err := client.Logical().Write("auth/cf/config", map[string]interface{}{
|
||||
"identity_ca_certificates": testCFCerts.CACertificate,
|
||||
"cf_api_addr": mockCFAPI.URL,
|
||||
"cf_username": cfAPI.AuthUsername,
|
||||
"cf_password": cfAPI.AuthPassword,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Configure a role to be used for logging in, another thing a Vault operator would do.
|
||||
if _, err := client.Logical().Write("auth/pcf/roles/test-role", map[string]interface{}{
|
||||
"bound_instance_ids": pcfAPI.FoundServiceGUID,
|
||||
"bound_organization_ids": pcfAPI.FoundOrgGUID,
|
||||
"bound_space_ids": pcfAPI.FoundSpaceGUID,
|
||||
"bound_application_ids": pcfAPI.FoundAppGUID,
|
||||
if _, err := client.Logical().Write("auth/cf/roles/test-role", map[string]interface{}{
|
||||
"bound_instance_ids": cfAPI.FoundServiceGUID,
|
||||
"bound_organization_ids": cfAPI.FoundOrgGUID,
|
||||
"bound_space_ids": cfAPI.FoundSpaceGUID,
|
||||
"bound_application_ids": cfAPI.FoundAppGUID,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
os.Setenv(credPCF.EnvVarInstanceCertificate, testPCFCerts.PathToInstanceCertificate)
|
||||
os.Setenv(credPCF.EnvVarInstanceKey, testPCFCerts.PathToInstanceKey)
|
||||
os.Setenv(credCF.EnvVarInstanceCertificate, testCFCerts.PathToInstanceCertificate)
|
||||
os.Setenv(credCF.EnvVarInstanceKey, testCFCerts.PathToInstanceKey)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
timer := time.AfterFunc(30*time.Second, func() {
|
||||
|
@ -97,8 +97,8 @@ func TestPCFEndToEnd(t *testing.T) {
|
|||
})
|
||||
defer timer.Stop()
|
||||
|
||||
am, err := agentpcf.NewPCFAuthMethod(&auth.AuthConfig{
|
||||
MountPath: "auth/pcf",
|
||||
am, err := agentcf.NewCFAuthMethod(&auth.AuthConfig{
|
||||
MountPath: "auth/cf",
|
||||
Config: map[string]interface{}{
|
||||
"role": "test-role",
|
||||
},
|
|
@ -178,6 +178,10 @@ func TestAuthEnableCommand_Run(t *testing.T) {
|
|||
backends = append(backends, strings.TrimPrefix(potPlug, "vault-plugin-auth-"))
|
||||
}
|
||||
}
|
||||
// Since "pcf" plugin in the Vault registry is also pointed at the "vault-plugin-auth-cf"
|
||||
// repository, we need to manually append it here so it'll tie out with our expected number
|
||||
// of credential backends.
|
||||
backends = append(backends, "pcf")
|
||||
|
||||
// Add 1 to account for the "token" backend, which is visible when you walk the filesystem but
|
||||
// is treated as special and excluded from the registry.
|
||||
|
|
|
@ -333,6 +333,7 @@ func TestPredict_Plugins(t *testing.T) {
|
|||
"cassandra-database-plugin",
|
||||
"centrify",
|
||||
"cert",
|
||||
"cf",
|
||||
"consul",
|
||||
"elasticsearch-database-plugin",
|
||||
"gcp",
|
||||
|
@ -357,7 +358,7 @@ func TestPredict_Plugins(t *testing.T) {
|
|||
"nomad",
|
||||
"oidc",
|
||||
"okta",
|
||||
"pcf",
|
||||
"pcf", // Deprecated.
|
||||
"pki",
|
||||
"postgresql",
|
||||
"postgresql-database-plugin",
|
||||
|
|
|
@ -25,9 +25,9 @@ import (
|
|||
|
||||
credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
|
||||
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
||||
credCF "github.com/hashicorp/vault-plugin-auth-cf"
|
||||
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||
credOIDC "github.com/hashicorp/vault-plugin-auth-jwt"
|
||||
credPCF "github.com/hashicorp/vault-plugin-auth-pcf"
|
||||
credAws "github.com/hashicorp/vault/builtin/credential/aws"
|
||||
credCert "github.com/hashicorp/vault/builtin/credential/cert"
|
||||
credGitHub "github.com/hashicorp/vault/builtin/credential/github"
|
||||
|
@ -160,12 +160,13 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
|||
"aws": &credAws.CLIHandler{},
|
||||
"centrify": &credCentrify.CLIHandler{},
|
||||
"cert": &credCert.CLIHandler{},
|
||||
"cf": &credCF.CLIHandler{},
|
||||
"gcp": &credGcp.CLIHandler{},
|
||||
"github": &credGitHub.CLIHandler{},
|
||||
"ldap": &credLdap.CLIHandler{},
|
||||
"oidc": &credOIDC.CLIHandler{},
|
||||
"okta": &credOkta.CLIHandler{},
|
||||
"pcf": &credPCF.CLIHandler{},
|
||||
"pcf": &credCF.CLIHandler{}, // Deprecated.
|
||||
"radius": &credUserpass.CLIHandler{
|
||||
DefaultMount: "radius",
|
||||
},
|
||||
|
|
2
go.mod
2
go.mod
|
@ -67,10 +67,10 @@ require (
|
|||
github.com/hashicorp/vault-plugin-auth-alicloud v0.5.2-0.20190814210027-93970f08f2ec
|
||||
github.com/hashicorp/vault-plugin-auth-azure v0.5.2-0.20190814210035-08e00d801115
|
||||
github.com/hashicorp/vault-plugin-auth-centrify v0.5.2-0.20190814210042-090ec2ed93ce
|
||||
github.com/hashicorp/vault-plugin-auth-cf v0.0.0-20190821162840-1c2205826fee
|
||||
github.com/hashicorp/vault-plugin-auth-gcp v0.5.2-0.20190814210049-1ccb3dc10102
|
||||
github.com/hashicorp/vault-plugin-auth-jwt v0.5.2-0.20190814210057-5e4c92d2b835
|
||||
github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.2-0.20190814210103-f64f0cb4d8cf
|
||||
github.com/hashicorp/vault-plugin-auth-pcf v0.0.0-20190814210109-476d6beb6ec0
|
||||
github.com/hashicorp/vault-plugin-database-elasticsearch v0.0.0-20190814210117-e079e01fbb93
|
||||
github.com/hashicorp/vault-plugin-secrets-ad v0.5.3-0.20190814210122-0f2fd536b250
|
||||
github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.2-0.20190814210129-4d18bec92f56
|
||||
|
|
4
go.sum
4
go.sum
|
@ -326,6 +326,8 @@ github.com/hashicorp/vault-plugin-auth-azure v0.5.2-0.20190814210035-08e00d80111
|
|||
github.com/hashicorp/vault-plugin-auth-azure v0.5.2-0.20190814210035-08e00d801115/go.mod h1:sRhTnkcbjJgPeES0ddCTq8S2waSakyMiWLUwO5J/Wjk=
|
||||
github.com/hashicorp/vault-plugin-auth-centrify v0.5.2-0.20190814210042-090ec2ed93ce h1:X8umWdCqSVk/75ZjEBDxYL+V8i+jK3KbJbFoyOryCww=
|
||||
github.com/hashicorp/vault-plugin-auth-centrify v0.5.2-0.20190814210042-090ec2ed93ce/go.mod h1:WstOCHERNbk2dblnY5MV9Qeh/hzTSQpVs5xPuyAzlBo=
|
||||
github.com/hashicorp/vault-plugin-auth-cf v0.0.0-20190821162840-1c2205826fee h1:gJG1PJGiqi+0M0HTYlwDyV5CyetLhFl9DxyMJre5H9Y=
|
||||
github.com/hashicorp/vault-plugin-auth-cf v0.0.0-20190821162840-1c2205826fee/go.mod h1:zOag32+pm1R4FFNhXMLP506Oesjoai3gHEEpxqUaTr0=
|
||||
github.com/hashicorp/vault-plugin-auth-gcp v0.5.1 h1:8DR00s+Wmc21i3sfzvsqW88VMdf6NI2ue+onGoHshww=
|
||||
github.com/hashicorp/vault-plugin-auth-gcp v0.5.1/go.mod h1:eLj92eX8MPI4vY1jaazVLF2sVbSAJ3LRHLRhF/pUmlI=
|
||||
github.com/hashicorp/vault-plugin-auth-gcp v0.5.2-0.20190814210049-1ccb3dc10102 h1:RTHVdxCDwxTq/4zZFkV+b8zexkSU5EOXkY2D/kAvyFU=
|
||||
|
@ -334,8 +336,6 @@ github.com/hashicorp/vault-plugin-auth-jwt v0.5.2-0.20190814210057-5e4c92d2b835
|
|||
github.com/hashicorp/vault-plugin-auth-jwt v0.5.2-0.20190814210057-5e4c92d2b835/go.mod h1:Ti2NPndKhSGpSL6gWg11n7TkmuI7318BIPeojayIVRU=
|
||||
github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.2-0.20190814210103-f64f0cb4d8cf h1:JnBSA5CnZps9JEX9RJZAdJ5tUVogWMIvVvatNmzGe38=
|
||||
github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.2-0.20190814210103-f64f0cb4d8cf/go.mod h1:qkrONCr71ckSCTItJQ1j9uet/faieZJ5c7+GZugTm7s=
|
||||
github.com/hashicorp/vault-plugin-auth-pcf v0.0.0-20190814210109-476d6beb6ec0 h1:d12XATwgTmHBAF5LLnpv4dSl3bEXjAU9Ahtf9gKDDFg=
|
||||
github.com/hashicorp/vault-plugin-auth-pcf v0.0.0-20190814210109-476d6beb6ec0/go.mod h1:d4nD8sbyQmb1XspLqkZkJzqmrdA2CoaFFRTRd3jHu0s=
|
||||
github.com/hashicorp/vault-plugin-database-elasticsearch v0.0.0-20190814210117-e079e01fbb93 h1:kXTV1ImOPgDGZxAlbEQfiXgnZY/34vfgnZVhI/tscmg=
|
||||
github.com/hashicorp/vault-plugin-database-elasticsearch v0.0.0-20190814210117-e079e01fbb93/go.mod h1:N9XpfMXjeLHBgUd8iy4avOC4mCSqUC7B/R8AtCYhcfE=
|
||||
github.com/hashicorp/vault-plugin-secrets-ad v0.5.3-0.20190814210122-0f2fd536b250 h1:+mm2cM5msg/USImbvnMS2yzCMBYMCO3CrvsATWGtHtY=
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
|
||||
credAzure "github.com/hashicorp/vault-plugin-auth-azure"
|
||||
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
|
||||
credCF "github.com/hashicorp/vault-plugin-auth-cf"
|
||||
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||
credJWT "github.com/hashicorp/vault-plugin-auth-jwt"
|
||||
credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
|
||||
credPCF "github.com/hashicorp/vault-plugin-auth-pcf"
|
||||
credAppId "github.com/hashicorp/vault/builtin/credential/app-id"
|
||||
credAppRole "github.com/hashicorp/vault/builtin/credential/approle"
|
||||
credAws "github.com/hashicorp/vault/builtin/credential/aws"
|
||||
|
@ -72,6 +72,7 @@ func newRegistry() *registry {
|
|||
"azure": credAzure.Factory,
|
||||
"centrify": credCentrify.Factory,
|
||||
"cert": credCert.Factory,
|
||||
"cf": credCF.Factory,
|
||||
"gcp": credGcp.Factory,
|
||||
"github": credGitHub.Factory,
|
||||
"jwt": credJWT.Factory,
|
||||
|
@ -79,7 +80,7 @@ func newRegistry() *registry {
|
|||
"ldap": credLdap.Factory,
|
||||
"oidc": credJWT.Factory,
|
||||
"okta": credOkta.Factory,
|
||||
"pcf": credPCF.Factory,
|
||||
"pcf": credCF.Factory, // Deprecated.
|
||||
"radius": credRadius.Factory,
|
||||
"userpass": credUserpass.Factory,
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
TOOL?=vault-plugin-auth-pcf
|
||||
TOOL?=vault-plugin-auth-cf
|
||||
TEST?=$$(go list ./... | grep -v /vendor/ | grep -v teamcity)
|
||||
VETARGS?=-asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -structtags -unsafeptr
|
||||
EXTERNAL_TOOLS=\
|
|
@ -1,21 +1,21 @@
|
|||
# vault-plugin-auth-pcf
|
||||
# vault-plugin-auth-cf
|
||||
|
||||
This plugin leverages PCF's [App and Container Identity Assurance](https://content.pivotal.io/blog/new-in-pcf-2-1-app-container-identity-assurance-via-automatic-cert-rotation)
|
||||
This plugin leverages Cloud Foundry's [App and Container Identity Assurance](https://content.pivotal.io/blog/new-in-pcf-2-1-app-container-identity-assurance-via-automatic-cert-rotation)
|
||||
for authenticating to Vault.
|
||||
|
||||
## Official Documentation
|
||||
|
||||
This plugin's docs reside in the following places:
|
||||
|
||||
- [Overview](https://www.vaultproject.io/docs/auth/pcf.html)
|
||||
- [API](https://www.vaultproject.io/api/auth/pcf/index.html)
|
||||
- [Overview](https://www.vaultproject.io/docs/auth/cf.html)
|
||||
- [API](https://www.vaultproject.io/api/auth/cf/index.html)
|
||||
|
||||
The documentation below is intended to further elaborate, and is targeted at those developing, using,
|
||||
troubleshooting, and maintaining this plugin.
|
||||
|
||||
## Known Risks
|
||||
|
||||
This authentication engine uses PCF's instance identity service to authenticate users to Vault. Because PCF
|
||||
This authentication engine uses Cloud Foundry's instance identity service to authenticate users to Vault. Because Cloud Foundry
|
||||
makes its CA certificate and **private key** available to certain users at any time, it's possible for someone
|
||||
with access to them to self-issue identity certificates that meet the criteria for a Vault role, allowing
|
||||
them to gain unintended access to Vault.
|
||||
|
@ -30,12 +30,12 @@ or through carefully limiting the users who can access CredHub.
|
|||
## Getting Started
|
||||
|
||||
The following guide provides instructions on how obtain the necessary credentials and certificates in order
|
||||
to set up the PCF auth method. The sample PCF endpoints uses `*.lagunaniguel.cf-app.com` which should be
|
||||
to set up the Cloud Foundry auth method. The sample Cloud Foundry endpoints uses `*.lagunaniguel.cf-app.com` which should be
|
||||
replaced with the appropriate endpoints for your environment.
|
||||
|
||||
### Obtaining Your Instance Identity CA Certificate
|
||||
|
||||
In most versions of PCF, instance identity is enabled out-of-the-box. Check by pulling your CA certificate,
|
||||
In most versions of Cloud Foundry, instance identity is enabled out-of-the-box. Check by pulling your CA certificate,
|
||||
which you'll need to configure this auth engine. There are undoubtedly multiple ways to do this, but this
|
||||
is how we did it.
|
||||
|
||||
|
@ -278,33 +278,33 @@ openssl s_client -showcerts -connect pcf.lagunaniguel.cf-app.com:443
|
|||
|
||||
You'll see a certificate outputted as part of the response, which should be broken
|
||||
out into a separate well-formatted file like the `ca.crt` above, and used for the
|
||||
`pcf_api_trusted_certificates` field.
|
||||
`cf_api_trusted_certificates` field.
|
||||
|
||||
## Downloading the Plugin
|
||||
|
||||
- `$ git clone git@github.com:hashicorp/vault-plugin-auth-pcf.git`
|
||||
- `$ cd vault-plugin-auth-pcf`
|
||||
- `$ PCF_HOME=$(pwd)`
|
||||
- `$ git clone git@github.com:hashicorp/vault-plugin-auth-cf.git`
|
||||
- `$ cd vault-plugin-auth-cf`
|
||||
- `$ CF_HOME=$(pwd)`
|
||||
|
||||
## Sample Usage
|
||||
|
||||
Please note that this example uses `generate-signature`, a tool installed through `$ make tools`.
|
||||
|
||||
First, enable the PCF auth engine.
|
||||
First, enable the CF auth engine.
|
||||
```
|
||||
$ vault auth enable pcf
|
||||
$ vault auth enable cf
|
||||
```
|
||||
|
||||
Next, configure the plugin. In the `config` call below, `certificates` is intended to be the instance
|
||||
identity CA certificate you pulled above.
|
||||
|
||||
```
|
||||
$ vault write auth/pcf/config \
|
||||
$ vault write auth/cf/config \
|
||||
identity_ca_certificates=@ca.crt \
|
||||
pcf_api_addr=https://api.sys.lagunaniguel.cf-app.com \
|
||||
pcf_username=vault \
|
||||
pcf_password=pa55word \
|
||||
pcf_api_trusted_certificates=@pcfapi.crt
|
||||
cf_api_addr=https://api.sys.lagunaniguel.cf-app.com \
|
||||
cf_username=vault \
|
||||
cf_password=pa55word \
|
||||
cf_api_trusted_certificates=@cfapi.crt
|
||||
```
|
||||
|
||||
Then, add a role that will be used to grant specific Vault policies to those logging in with it. When a constraint like
|
||||
|
@ -325,7 +325,7 @@ $ openssl crl2pkcs7 -nocrl -certfile instance.crt | openssl pkcs7 -print_certs -
|
|||
Also, by default, the IP address on the certificate presented at login must match that of the caller. However, if
|
||||
your callers tend to be proxied, this may not work for you. If that's the case, set `disable_ip_matching` to true.
|
||||
```
|
||||
$ vault write auth/pcf/roles/test-role \
|
||||
$ vault write auth/cf/roles/test-role \
|
||||
bound_application_ids=2d3e834a-3a25-4591-974c-fa5626d5d0a1 \
|
||||
bound_space_ids=3d2eba6b-ef19-44d5-91dd-1975b0db5cc9 \
|
||||
bound_organization_ids=34a878d0-c2f9-4521-ba73-a9f664e82c7bf \
|
||||
|
@ -335,14 +335,14 @@ $ vault write auth/pcf/roles/test-role \
|
|||
Logging in is intended to be performed using your `CF_INSTANCE_CERT` and `CF_INSTANCE_KEY`. This is an example of how
|
||||
it can be done.
|
||||
```
|
||||
$ export CF_INSTANCE_CERT=$PCF_HOME/testdata/fake-certificates/instance.crt
|
||||
$ export CF_INSTANCE_KEY=$PCF_HOME/testdata/fake-certificates/instance.key
|
||||
$ vault login -method=pcf role=test-role
|
||||
$ export CF_INSTANCE_CERT=$CF_HOME/testdata/fake-certificates/instance.crt
|
||||
$ export CF_INSTANCE_KEY=$CF_HOME/testdata/fake-certificates/instance.key
|
||||
$ vault login -method=cf role=test-role
|
||||
```
|
||||
|
||||
### Updating the CA Certificate
|
||||
|
||||
In PCF, most CA certificates expire after 4 years. However, it's possible to configure your own CA certificate for the
|
||||
In Cloud Foundry, most CA certificates expire after 4 years. However, it's possible to configure your own CA certificate for the
|
||||
instance identity service, and its expiration date could vary. Either way, sometimes CA certificates expire and it may
|
||||
be necessary to have multiple configured so the beginning date of once commences when another expires.
|
||||
|
||||
|
@ -350,7 +350,7 @@ To configure multiple certificates, simply update the config to include the curr
|
|||
```
|
||||
$ CURRENT=$(cat /path/to/current-ca.crt)
|
||||
$ FUTURE=$(cat /path/to/future-ca.crt)
|
||||
$ vault write auth/vault-plugin-auth-pcf/config certificates="$CURRENT,$FUTURE"
|
||||
$ vault write auth/vault-plugin-auth-cf/config certificates="$CURRENT,$FUTURE"
|
||||
```
|
||||
|
||||
All other configured values will remain untouched; however, the previous value for `certificates` will be overwritten
|
||||
|
@ -362,20 +362,20 @@ login will succeed.
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
### Obtaining a Certificate Error from the PCF API
|
||||
### Obtaining a Certificate Error from the CF API
|
||||
|
||||
When configuring this plugin, you may encounter an error like:
|
||||
```
|
||||
Error writing data to auth/pcf/config: Error making API request.
|
||||
Error writing data to auth/cf/config: Error making API request.
|
||||
|
||||
URL: PUT http://127.0.0.1:8200/v1/auth/pcf/config
|
||||
URL: PUT http://127.0.0.1:8200/v1/auth/cf/config
|
||||
Code: 500. Errors:
|
||||
|
||||
* 1 error occurred:
|
||||
* unable to establish an initial connection to the PCF API: Could not get api /v2/info: Get https://api.sys.lagunaniguel.cf-app.com/v2/info: x509: certificate signed by unknown authority
|
||||
* unable to establish an initial connection to the CF API: Could not get api /v2/info: Get https://api.sys.lagunaniguel.cf-app.com/v2/info: x509: certificate signed by unknown authority
|
||||
```
|
||||
|
||||
To resolve this error, review instructions above regarding setting the `pcf_api_trusted_certificates` field.
|
||||
To resolve this error, review instructions above regarding setting the `cf_api_trusted_certificates` field.
|
||||
|
||||
### verify-certs
|
||||
|
||||
|
@ -388,7 +388,7 @@ verify-certs -ca-cert=local/path/to/ca.crt -instance-cert=local/path/to/instance
|
|||
```
|
||||
The `ca-cert` should be the cert that was used to issue the given client certificate.
|
||||
|
||||
The `instance-cert` given should be the value for the `CF_INSTANCE_CERT` variable in the PCF environment you're
|
||||
The `instance-cert` given should be the value for the `CF_INSTANCE_CERT` variable in the Cloud Foundry environment you're
|
||||
using, and the `instance-key` should be the value for the `CF_INSTANCE_KEY`.
|
||||
|
||||
The tool does take the _local path to_ these certificates, so you'll need to gather them and place them on your
|
||||
|
@ -396,7 +396,7 @@ local machine to verify they all will work together.
|
|||
|
||||
### generate-signature
|
||||
|
||||
This tool, installed by `make tools`, is for generating a valid signature to be used for signing into Vault via PCF.
|
||||
This tool, installed by `make tools`, is for generating a valid signature to be used for signing into Vault via Cloud Foundry.
|
||||
|
||||
It can be used as a standalone tool for generating a signature like so:
|
||||
```
|
||||
|
@ -414,25 +414,25 @@ export CF_INSTANCE_KEY=path/to/instance.key
|
|||
export SIGNING_TIME=$(date -u)
|
||||
export ROLE='test-role'
|
||||
|
||||
vault write auth/vault-plugin-auth-pcf/login \
|
||||
vault write auth/vault-plugin-auth-cf/login \
|
||||
role=$ROLE \
|
||||
certificate=$CF_INSTANCE_CERT \
|
||||
signing-time=SIGNING_TIME \
|
||||
signature=$(generate-signature)
|
||||
```
|
||||
If the tool is being run in a PCF environment already containing the `CF_INSTANCE_CERT` and `CF_INSTANCE_KEY`, those
|
||||
If the tool is being run in a Cloud Foundry environment already containing the `CF_INSTANCE_CERT` and `CF_INSTANCE_KEY`, those
|
||||
variables obviously won't need to be manually set before the tool is used and can just be pulled as they are.
|
||||
|
||||
## Developing
|
||||
|
||||
### mock-pcf-server
|
||||
### mock-cf-server
|
||||
|
||||
This tool, installed by `make tools`, is for use in development. It lets you run a mocked PCF server for use in local
|
||||
testing, with output that can be used as the `pcf_api_addr`, `pcf_username`, and `pcf_password` in your config.
|
||||
This tool, installed by `make tools`, is for use in development. It lets you run a mocked Cloud Foundry server for use in local
|
||||
testing, with output that can be used as the `cf_api_addr`, `cf_username`, and `cf_password` in your config.
|
||||
|
||||
Example use:
|
||||
```
|
||||
$ mock-pcf-server
|
||||
$ mock-cf-server
|
||||
running at http://127.0.0.1:33671
|
||||
username is username
|
||||
password is password
|
||||
|
@ -520,7 +520,7 @@ This signature should be placed in the `signature` field of login requests.
|
|||
|
||||
If you implement the algorithm above and still encounter errors logging in,
|
||||
it may help to generate test certificates using the `make-test-certs` tool.
|
||||
These certificates are accurate enough mocks of real PCF certificates, and
|
||||
These certificates are accurate enough mocks of real Cloud Foundry certificates, and
|
||||
are used for testing. Using this tool to generate your test certificates will
|
||||
rule out any error with the certificates you may have created yourself.
|
||||
|
||||
|
@ -537,7 +537,7 @@ path to key to use as CF_INSTANCE_KEY: /tmp/5c08f79d-b2a5-c211-2862-00fe0a3b647d
|
|||
- [Java](https://github.com/tyrannosaurus-becks/vault-tools-auth-pcf)
|
||||
- Python:
|
||||
```
|
||||
## PCF signature creation example in Python using the [Cryptography](https://cryptography.io) library
|
||||
## CF signature creation example in Python using the [Cryptography](https://cryptography.io) library
|
||||
import base64
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
|
@ -576,25 +576,25 @@ make dev
|
|||
make tools
|
||||
|
||||
# In one shell window, run Vault with the plugin available in the catalog.
|
||||
vault server -dev -dev-root-token-id=root -dev-plugin-dir=$PCF_HOME/bin -log-level=debug
|
||||
vault server -dev -dev-root-token-id=root -dev-plugin-dir=$CF_HOME/bin -log-level=debug
|
||||
|
||||
# In another shell window, run a mock of the PCF API so the plugin's client calls won't fail.
|
||||
mock-pcf-server
|
||||
# In another shell window, run a mock of the CF API so the plugin's client calls won't fail.
|
||||
mock-cf-server
|
||||
|
||||
# In another shell window, execute the following commands to exercise each endpoint.
|
||||
export VAULT_ADDR=http://localhost:8200
|
||||
export VAULT_TOKEN=root
|
||||
export MOCK_PCF_SERVER_ADDR='something' # ex. http://127.0.0.1:32937
|
||||
export MOCK_CF_SERVER_ADDR='something' # ex. http://127.0.0.1:32937
|
||||
|
||||
vault auth enable vault-plugin-auth-pcf
|
||||
vault auth enable vault-plugin-auth-cf
|
||||
|
||||
vault write auth/vault-plugin-auth-pcf/config \
|
||||
certificates=@$PCF_HOME/testdata/fake-certificates/ca.crt \
|
||||
pcf_api_addr=$MOCK_PCF_SERVER_ADDR \
|
||||
pcf_username=username \
|
||||
pcf_password=password
|
||||
vault write auth/vault-plugin-auth-cf/config \
|
||||
certificates=@$CF_HOME/testdata/fake-certificates/ca.crt \
|
||||
cf_api_addr=$MOCK_CF_SERVER_ADDR \
|
||||
cf_username=username \
|
||||
cf_password=password
|
||||
|
||||
vault write auth/vault-plugin-auth-pcf/roles/test-role \
|
||||
vault write auth/vault-plugin-auth-cf/roles/test-role \
|
||||
bound_application_ids=2d3e834a-3a25-4591-974c-fa5626d5d0a1 \
|
||||
bound_space_ids=3d2eba6b-ef19-44d5-91dd-1975b0db5cc9 \
|
||||
bound_organization_ids=34a878d0-c2f9-4521-ba73-a9f664e82c7bf \
|
||||
|
@ -605,11 +605,11 @@ vault write auth/vault-plugin-auth-pcf/roles/test-role \
|
|||
max_ttl=86400s \
|
||||
period=86400s
|
||||
|
||||
export CF_INSTANCE_CERT=$PCF_HOME/testdata/fake-certificates/instance.crt
|
||||
export CF_INSTANCE_KEY=$PCF_HOME/testdata/fake-certificates/instance.key
|
||||
export CF_INSTANCE_CERT=$CF_HOME/testdata/fake-certificates/instance.crt
|
||||
export CF_INSTANCE_KEY=$CF_HOME/testdata/fake-certificates/instance.key
|
||||
export SIGNING_TIME=$(date -u)
|
||||
export ROLE='test-role'
|
||||
vault write auth/vault-plugin-auth-pcf/login \
|
||||
vault write auth/vault-plugin-auth-cf/login \
|
||||
role=$ROLE \
|
||||
certificate=@$CF_INSTANCE_CERT \
|
||||
signing_time="$SIGNING_TIME" \
|
||||
|
@ -617,7 +617,7 @@ vault write auth/vault-plugin-auth-pcf/login \
|
|||
|
||||
vault token renew <token>
|
||||
|
||||
CURRENT=$(cat $PCF_HOME/testdata/fake-certificates/ca.crt)
|
||||
FUTURE=$(cat $PCF_HOME/testdata/fake-certificates/ca.crt)
|
||||
vault write auth/vault-plugin-auth-pcf/config certificates="$CURRENT,$FUTURE"
|
||||
CURRENT=$(cat $CF_HOME/testdata/fake-certificates/ca.crt)
|
||||
FUTURE=$(cat $CF_HOME/testdata/fake-certificates/ca.crt)
|
||||
vault write auth/vault-plugin-auth-cf/config certificates="$CURRENT,$FUTURE"
|
||||
```
|
|
@ -1,4 +1,4 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
const (
|
||||
// These env vars are used frequently to pull the client certificate and private key
|
||||
// from PCF containers; thus are placed here for ease of discovery and use from
|
||||
// from CF containers; thus are placed here for ease of discovery and use from
|
||||
// outside packages.
|
||||
EnvVarInstanceCertificate = "CF_INSTANCE_CERT"
|
||||
EnvVarInstanceKey = "CF_INSTANCE_KEY"
|
||||
|
@ -43,7 +43,7 @@ type backend struct {
|
|||
}
|
||||
|
||||
const backendHelp = `
|
||||
The PCF auth backend supports logging in using PCF's identity service.
|
||||
The CF auth backend supports logging in using CF's identity service.
|
||||
Once a CA certificate is configured, and Vault is configured to consume
|
||||
PCF's API, PCF's instance identity credentials can be used to authenticate.'
|
||||
CF's API, CF's instance identity credentials can be used to authenticate.'
|
||||
`
|
|
@ -1,4 +1,4 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
@ -8,7 +8,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/signatures"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/signatures"
|
||||
"github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ type CLIHandler struct{}
|
|||
func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, error) {
|
||||
mount, ok := m["mount"]
|
||||
if !ok {
|
||||
mount = "pcf"
|
||||
mount = "cf"
|
||||
}
|
||||
|
||||
role := m["role"]
|
||||
|
@ -79,33 +79,33 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
|
|||
|
||||
func (h *CLIHandler) Help() string {
|
||||
help := `
|
||||
Usage: vault login -method=pcf [CONFIG K=V...]
|
||||
Usage: vault login -method=cf [CONFIG K=V...]
|
||||
|
||||
The PCF auth method allows users to authenticate using PCF's instance identity service.
|
||||
The CF auth method allows users to authenticate using CF's instance identity service.
|
||||
|
||||
The PCF credentials may be specified explicitly via the command line:
|
||||
The CF credentials may be specified explicitly via the command line:
|
||||
|
||||
$ vault login -method=pcf role=...
|
||||
$ vault login -method=cf role=...
|
||||
|
||||
This will automatically pull from the CF_INSTANCE_CERT and CF_INSTANCE_KEY values
|
||||
in your local environment. If they're not available or you wish to override them,
|
||||
they may also be supplied explicitly:
|
||||
|
||||
$ vault login -method=pcf role=... cf_instance_cert=... cf_instance_key=...
|
||||
$ vault login -method=cf role=... cf_instance_cert=... cf_instance_key=...
|
||||
|
||||
Configuration:
|
||||
|
||||
cf_instance_cert=<string>
|
||||
Explicit value to use for the path to the PCF instance certificate.
|
||||
Explicit value to use for the path to the CF instance certificate.
|
||||
|
||||
cf_instance_key=<string>
|
||||
Explicit value to use for the path to the PCF instance key.
|
||||
Explicit value to use for the path to the CF instance key.
|
||||
|
||||
mount=<string>
|
||||
Path where the PCF credential method is mounted. This is usually provided
|
||||
Path where the CF credential method is mounted. This is usually provided
|
||||
via the -path flag in the "vault login" command, but it can be specified
|
||||
here as well. If specified here, it takes precedence over the value for
|
||||
-path. The default value is "pcf".
|
||||
-path. The default value is "cf".
|
||||
|
||||
role=<string>
|
||||
Name of the role to request a token against
|
|
@ -1,4 +1,4 @@
|
|||
module github.com/hashicorp/vault-plugin-auth-pcf
|
||||
module github.com/hashicorp/vault-plugin-auth-cf
|
||||
|
||||
go 1.12
|
||||
|
|
@ -8,14 +8,14 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// NewPCFCertificateFromx509 converts a x509 certificate to a valid, well-formed PCF certificate,
|
||||
// NewCFCertificateFromx509 converts a x509 certificate to a valid, well-formed CF certificate,
|
||||
// erroring if this isn't possible.
|
||||
func NewPCFCertificateFromx509(certificate *x509.Certificate) (*PCFCertificate, error) {
|
||||
func NewCFCertificateFromx509(certificate *x509.Certificate) (*CFCertificate, error) {
|
||||
if len(certificate.IPAddresses) != 1 {
|
||||
return nil, fmt.Errorf("valid PCF certs have one IP address, but this has %s", certificate.IPAddresses)
|
||||
return nil, fmt.Errorf("valid CF certs have one IP address, but this has %s", certificate.IPAddresses)
|
||||
}
|
||||
|
||||
pcfCert := &PCFCertificate{
|
||||
cfCert := &CFCertificate{
|
||||
InstanceID: certificate.Subject.CommonName,
|
||||
IPAddress: certificate.IPAddresses[0].String(),
|
||||
}
|
||||
|
@ -25,17 +25,17 @@ func NewPCFCertificateFromx509(certificate *x509.Certificate) (*PCFCertificate,
|
|||
apps := 0
|
||||
for _, ou := range certificate.Subject.OrganizationalUnit {
|
||||
if strings.HasPrefix(ou, "space:") {
|
||||
pcfCert.SpaceID = strings.Split(ou, "space:")[1]
|
||||
cfCert.SpaceID = strings.Split(ou, "space:")[1]
|
||||
spaces++
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(ou, "organization:") {
|
||||
pcfCert.OrgID = strings.Split(ou, "organization:")[1]
|
||||
cfCert.OrgID = strings.Split(ou, "organization:")[1]
|
||||
orgs++
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(ou, "app:") {
|
||||
pcfCert.AppID = strings.Split(ou, "app:")[1]
|
||||
cfCert.AppID = strings.Split(ou, "app:")[1]
|
||||
apps++
|
||||
continue
|
||||
}
|
||||
|
@ -49,35 +49,35 @@ func NewPCFCertificateFromx509(certificate *x509.Certificate) (*PCFCertificate,
|
|||
if apps > 1 {
|
||||
return nil, fmt.Errorf("expected 1 app but received %d", apps)
|
||||
}
|
||||
if err := pcfCert.validate(); err != nil {
|
||||
if err := cfCert.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pcfCert, nil
|
||||
return cfCert, nil
|
||||
}
|
||||
|
||||
// NewPCFCertificateFromx509 converts the given fields to a valid, well-formed PCF certificate,
|
||||
// NewCFCertificateFromx509 converts the given fields to a valid, well-formed CF certificate,
|
||||
// erroring if this isn't possible.
|
||||
func NewPCFCertificate(instanceID, orgID, spaceID, appID, ipAddress string) (*PCFCertificate, error) {
|
||||
pcfCert := &PCFCertificate{
|
||||
func NewCFCertificate(instanceID, orgID, spaceID, appID, ipAddress string) (*CFCertificate, error) {
|
||||
cfCert := &CFCertificate{
|
||||
InstanceID: instanceID,
|
||||
OrgID: orgID,
|
||||
SpaceID: spaceID,
|
||||
AppID: appID,
|
||||
IPAddress: ipAddress,
|
||||
}
|
||||
if err := pcfCert.validate(); err != nil {
|
||||
if err := cfCert.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pcfCert, nil
|
||||
return cfCert, nil
|
||||
}
|
||||
|
||||
// PCFCertificate isn't intended to be instantiated directly; but rather through one of the New
|
||||
// CFCertificate isn't intended to be instantiated directly; but rather through one of the New
|
||||
// methods, which contain logic validating that the expected fields exist.
|
||||
type PCFCertificate struct {
|
||||
type CFCertificate struct {
|
||||
InstanceID, OrgID, SpaceID, AppID, IPAddress string
|
||||
}
|
||||
|
||||
func (c *PCFCertificate) validate() error {
|
||||
func (c *CFCertificate) validate() error {
|
||||
if c.InstanceID == "" {
|
||||
return errors.New("no instance ID on given certificate")
|
||||
}
|
54
vendor/github.com/hashicorp/vault-plugin-auth-cf/models/configuration.go
generated
vendored
Normal file
54
vendor/github.com/hashicorp/vault-plugin-auth-cf/models/configuration.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// Configuration is the config as it's reflected in Vault's storage system.
|
||||
type Configuration struct {
|
||||
// Version 0 had the following fields:
|
||||
// PCFAPICertificates []string `json:"pcf_api_trusted_certificates"`
|
||||
// PCFAPIAddr string `json:"pcf_api_addr"`
|
||||
// PCFUsername string `json:"pcf_username"`
|
||||
// PCFPassword string `json:"pcf_password"`
|
||||
// Version 1 is the present version and it adds support for the following fields:
|
||||
// CFAPICertificates []string `json:"cf_api_trusted_certificates"`
|
||||
// CFAPIAddr string `json:"cf_api_addr"`
|
||||
// CFUsername string `json:"cf_username"`
|
||||
// CFPassword string `json:"cf_password"`
|
||||
// Version 2 is in the future, and we intend to deprecate the fields noted in Version 0.
|
||||
Version int `json:"version"`
|
||||
|
||||
// IdentityCACertificates are the CA certificates that should be used for verifying client certificates.
|
||||
IdentityCACertificates []string `json:"identity_ca_certificates"`
|
||||
|
||||
// IdentityCACertificates that, if presented by the CF API, should be trusted.
|
||||
CFAPICertificates []string `json:"cf_api_trusted_certificates"`
|
||||
|
||||
// CFAPIAddr is the address of CF's API, ex: "https://api.dev.cfdev.sh" or "http://127.0.0.1:33671"
|
||||
CFAPIAddr string `json:"cf_api_addr"`
|
||||
|
||||
// The username for the CF API.
|
||||
CFUsername string `json:"cf_username"`
|
||||
|
||||
// The password for the CF API.
|
||||
CFPassword string `json:"cf_password"`
|
||||
|
||||
// The maximum seconds old a login request's signing time can be.
|
||||
// This is configurable because in some test environments we found as much as 2 hours of clock drift.
|
||||
LoginMaxSecNotBefore time.Duration `json:"login_max_seconds_not_before"`
|
||||
|
||||
// The maximum seconds ahead a login request's signing time can be.
|
||||
// This is configurable because in some test environments we found as much as 2 hours of clock drift.
|
||||
LoginMaxSecNotAfter time.Duration `json:"login_max_seconds_not_after"`
|
||||
|
||||
// Deprecated: use CFAPICertificates instead.
|
||||
PCFAPICertificates []string `json:"pcf_api_trusted_certificates"`
|
||||
|
||||
// Deprecated: use CFAPIAddr instead.
|
||||
PCFAPIAddr string `json:"pcf_api_addr"`
|
||||
|
||||
// Deprecated: use CFUsername instead.
|
||||
PCFUsername string `json:"pcf_username"`
|
||||
|
||||
// Deprecated: use CFPassword instead.
|
||||
PCFPassword string `json:"pcf_password"`
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -6,8 +6,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/models"
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/util"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/models"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/util"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
@ -19,7 +19,6 @@ func (b *backend) pathConfig() *framework.Path {
|
|||
Pattern: "config",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"identity_ca_certificates": {
|
||||
Required: true,
|
||||
Type: framework.TypeStringSlice,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "Identity CA Certificates",
|
||||
|
@ -27,40 +26,75 @@ func (b *backend) pathConfig() *framework.Path {
|
|||
},
|
||||
Description: "The PEM-format CA certificates that are required to have issued the instance certificates presented for logging in.",
|
||||
},
|
||||
"pcf_api_trusted_certificates": {
|
||||
"cf_api_trusted_certificates": {
|
||||
Type: framework.TypeStringSlice,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "PCF API Trusted IdentityCACertificates",
|
||||
Name: "CF API Trusted IdentityCACertificates",
|
||||
Value: `-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----`,
|
||||
},
|
||||
Description: "The PEM-format CA certificates that are acceptable for the PCF API to present.",
|
||||
Description: "The PEM-format CA certificates that are acceptable for the CF API to present.",
|
||||
},
|
||||
"pcf_api_addr": {
|
||||
Required: true,
|
||||
"cf_api_addr": {
|
||||
Type: framework.TypeString,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "PCF API Address",
|
||||
Name: "CF API Address",
|
||||
Value: "https://api.10.244.0.34.xip.io",
|
||||
},
|
||||
Description: "PCF’s API address.",
|
||||
Description: "CF’s API address.",
|
||||
},
|
||||
"pcf_username": {
|
||||
Required: true,
|
||||
"cf_username": {
|
||||
Type: framework.TypeString,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "PCF API Username",
|
||||
Name: "CF API Username",
|
||||
Value: "admin",
|
||||
},
|
||||
Description: "The username for PCF’s API.",
|
||||
Description: "The username for CF’s API.",
|
||||
},
|
||||
"pcf_password": {
|
||||
Required: true,
|
||||
"cf_password": {
|
||||
Type: framework.TypeString,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "PCF API Password",
|
||||
Name: "CF API Password",
|
||||
Sensitive: true,
|
||||
},
|
||||
Description: "The password for PCF’s API.",
|
||||
Description: "The password for CF’s API.",
|
||||
},
|
||||
// These fields were in the original release, but are being deprecated because Cloud Foundry is moving
|
||||
// away from using "PCF" to refer to themselves.
|
||||
"pcf_api_trusted_certificates": {
|
||||
Deprecated: true,
|
||||
Type: framework.TypeStringSlice,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "CF API Trusted IdentityCACertificates",
|
||||
Value: `-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----`,
|
||||
},
|
||||
Description: `Deprecated. Please use "cf_api_trusted_certificates".`,
|
||||
},
|
||||
"pcf_api_addr": {
|
||||
Deprecated: true,
|
||||
Type: framework.TypeString,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "CF API Address",
|
||||
Value: "https://api.10.244.0.34.xip.io",
|
||||
},
|
||||
Description: `Deprecated. Please use "cf_api_addr".`,
|
||||
},
|
||||
"pcf_username": {
|
||||
Deprecated: true,
|
||||
Type: framework.TypeString,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "CF API Username",
|
||||
Value: "admin",
|
||||
},
|
||||
Description: `Deprecated. Please use "cf_username".`,
|
||||
},
|
||||
"pcf_password": {
|
||||
Deprecated: true,
|
||||
Type: framework.TypeString,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "CF API Password",
|
||||
Sensitive: true,
|
||||
},
|
||||
Description: `Deprecated. Please use "cf_password".`,
|
||||
},
|
||||
"login_max_seconds_not_before": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
|
@ -109,23 +143,35 @@ func (b *backend) operationConfigCreateUpdate(ctx context.Context, req *logical.
|
|||
}
|
||||
if config == nil {
|
||||
// They're creating a config.
|
||||
// All new configs will be created as config version 1.
|
||||
identityCACerts := data.Get("identity_ca_certificates").([]string)
|
||||
if len(identityCACerts) == 0 {
|
||||
return logical.ErrorResponse("'identity_ca_certificates' is required"), nil
|
||||
}
|
||||
pcfApiAddr := data.Get("pcf_api_addr").(string)
|
||||
if pcfApiAddr == "" {
|
||||
return logical.ErrorResponse("'pcf_api_addr' is required"), nil
|
||||
|
||||
cfApiAddrIfc, ok := data.GetFirst("cf_api_addr", "pcf_api_addr")
|
||||
if !ok {
|
||||
return logical.ErrorResponse("'cf_api_addr' is required"), nil
|
||||
}
|
||||
pcfUsername := data.Get("pcf_username").(string)
|
||||
if pcfUsername == "" {
|
||||
return logical.ErrorResponse("'pcf_username' is required"), nil
|
||||
cfApiAddr := cfApiAddrIfc.(string)
|
||||
|
||||
cfUsernameIfc, ok := data.GetFirst("cf_username", "pcf_username")
|
||||
if !ok {
|
||||
return logical.ErrorResponse("'cf_username' is required"), nil
|
||||
}
|
||||
pcfPassword := data.Get("pcf_password").(string)
|
||||
if pcfPassword == "" {
|
||||
return logical.ErrorResponse("'pcf_password' is required"), nil
|
||||
cfUsername := cfUsernameIfc.(string)
|
||||
|
||||
cfPasswordIfc, ok := data.GetFirst("cf_password", "pcf_password")
|
||||
if !ok {
|
||||
return logical.ErrorResponse("'cf_password' is required"), nil
|
||||
}
|
||||
cfPassword := cfPasswordIfc.(string)
|
||||
|
||||
var cfApiCertificates []string
|
||||
cfApiCertificatesIfc, ok := data.GetFirst("cf_api_trusted_certificates", "pcf_api_trusted_certificates")
|
||||
if ok {
|
||||
cfApiCertificates = cfApiCertificatesIfc.([]string)
|
||||
}
|
||||
pcfApiCertificates := data.Get("pcf_api_trusted_certificates").([]string)
|
||||
|
||||
// Default this to 5 minutes.
|
||||
loginMaxSecNotBefore := 300 * time.Second
|
||||
|
@ -139,30 +185,33 @@ func (b *backend) operationConfigCreateUpdate(ctx context.Context, req *logical.
|
|||
loginMaxSecNotAfter = time.Duration(raw.(int)) * time.Second
|
||||
}
|
||||
config = &models.Configuration{
|
||||
Version: 1,
|
||||
IdentityCACertificates: identityCACerts,
|
||||
PCFAPICertificates: pcfApiCertificates,
|
||||
PCFAPIAddr: pcfApiAddr,
|
||||
PCFUsername: pcfUsername,
|
||||
PCFPassword: pcfPassword,
|
||||
CFAPICertificates: cfApiCertificates,
|
||||
CFAPIAddr: cfApiAddr,
|
||||
CFUsername: cfUsername,
|
||||
CFPassword: cfPassword,
|
||||
LoginMaxSecNotBefore: loginMaxSecNotBefore,
|
||||
LoginMaxSecNotAfter: loginMaxSecNotAfter,
|
||||
}
|
||||
} else {
|
||||
// They're updating a config. Only update the fields that have been sent in the call.
|
||||
// The stored config will have already handled any version upgrades necessary on read,
|
||||
// so here we only need to deal with setting up the present version of the config.
|
||||
if raw, ok := data.GetOk("identity_ca_certificates"); ok {
|
||||
config.IdentityCACertificates = raw.([]string)
|
||||
}
|
||||
if raw, ok := data.GetOk("pcf_api_trusted_certificates"); ok {
|
||||
config.PCFAPICertificates = raw.([]string)
|
||||
if raw, ok := data.GetFirst("cf_api_trusted_certificates", "pcf_api_trusted_certificates"); ok {
|
||||
config.CFAPICertificates = raw.([]string)
|
||||
}
|
||||
if raw, ok := data.GetOk("pcf_api_addr"); ok {
|
||||
config.PCFAPIAddr = raw.(string)
|
||||
if raw, ok := data.GetFirst("cf_api_addr", "pcf_api_addr"); ok {
|
||||
config.CFAPIAddr = raw.(string)
|
||||
}
|
||||
if raw, ok := data.GetOk("pcf_username"); ok {
|
||||
config.PCFUsername = raw.(string)
|
||||
if raw, ok := data.GetFirst("cf_username", "pcf_username"); ok {
|
||||
config.CFUsername = raw.(string)
|
||||
}
|
||||
if raw, ok := data.GetOk("pcf_password"); ok {
|
||||
config.PCFPassword = raw.(string)
|
||||
if raw, ok := data.GetFirst("cf_password", "pcf_password"); ok {
|
||||
config.CFPassword = raw.(string)
|
||||
}
|
||||
if raw, ok := data.GetOk("login_max_seconds_not_before"); ok {
|
||||
config.LoginMaxSecNotBefore = time.Duration(raw.(int)) * time.Second
|
||||
|
@ -174,25 +223,21 @@ func (b *backend) operationConfigCreateUpdate(ctx context.Context, req *logical.
|
|||
|
||||
// To give early and explicit feedback, make sure the config works by executing a test call
|
||||
// and checking that the API version is supported. If they don't have API v2 running, we would
|
||||
// probably expect a timeout of some sort below because it's first called in the NewPCFClient
|
||||
// probably expect a timeout of some sort below because it's first called in the NewCFClient
|
||||
// method.
|
||||
client, err := util.NewPCFClient(config)
|
||||
client, err := util.NewCFClient(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to establish an initial connection to the PCF API: %s", err)
|
||||
return nil, fmt.Errorf("unable to establish an initial connection to the CF API: %s", err)
|
||||
}
|
||||
info, err := client.GetInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !strings.HasPrefix(info.APIVersion, "2.") {
|
||||
return nil, fmt.Errorf("the PCF auth plugin only supports version 2.X.X of the PCF API")
|
||||
return nil, fmt.Errorf("the CF auth plugin only supports version 2.X.X of the CF API")
|
||||
}
|
||||
|
||||
entry, err := logical.StorageEntryJSON(configStorageKey, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := req.Storage.Put(ctx, entry); err != nil {
|
||||
if err := storeConfig(ctx, req.Storage, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
|
@ -206,16 +251,32 @@ func (b *backend) operationConfigRead(ctx context.Context, req *logical.Request,
|
|||
if config == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &logical.Response{
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"version": config.Version,
|
||||
"identity_ca_certificates": config.IdentityCACertificates,
|
||||
"pcf_api_trusted_certificates": config.PCFAPICertificates,
|
||||
"pcf_api_addr": config.PCFAPIAddr,
|
||||
"pcf_username": config.PCFUsername,
|
||||
"cf_api_trusted_certificates": config.CFAPICertificates,
|
||||
"cf_api_addr": config.CFAPIAddr,
|
||||
"cf_username": config.CFUsername,
|
||||
"login_max_seconds_not_before": config.LoginMaxSecNotBefore / time.Second,
|
||||
"login_max_seconds_not_after": config.LoginMaxSecNotAfter / time.Second,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
// Populate any deprecated values and warn about them. These should just be stripped when we go to
|
||||
// version 2 of the config.
|
||||
if len(config.PCFAPICertificates) > 0 {
|
||||
resp.Data["pcf_api_trusted_certificates"] = config.PCFAPICertificates
|
||||
resp.AddWarning(deprecationText("cf_api_trusted_certificates", "pcf_api_trusted_certificates"))
|
||||
}
|
||||
if config.PCFAPIAddr != "" {
|
||||
resp.Data["pcf_api_addr"] = config.PCFAPIAddr
|
||||
resp.AddWarning(deprecationText("cf_api_addr", "pcf_api_addr"))
|
||||
}
|
||||
if config.PCFUsername != "" {
|
||||
resp.Data["pcf_username"] = config.PCFUsername
|
||||
resp.AddWarning(deprecationText("cf_username", "pcf_username"))
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) operationConfigDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
|
@ -238,15 +299,47 @@ func config(ctx context.Context, storage logical.Storage) (*models.Configuration
|
|||
if err := entry.DecodeJSON(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Perform config version migrations if needed.
|
||||
if config.Version == 0 {
|
||||
if config.CFAPIAddr == "" && config.PCFAPIAddr != "" {
|
||||
config.CFAPIAddr = config.PCFAPIAddr
|
||||
}
|
||||
if len(config.CFAPICertificates) == 0 && len(config.PCFAPICertificates) > 0 {
|
||||
config.CFAPICertificates = config.PCFAPICertificates
|
||||
}
|
||||
if config.CFUsername == "" && config.PCFUsername != "" {
|
||||
config.CFUsername = config.PCFUsername
|
||||
}
|
||||
if config.CFPassword == "" && config.PCFPassword != "" {
|
||||
config.CFPassword = config.PCFPassword
|
||||
}
|
||||
config.Version = 1
|
||||
if err := storeConfig(ctx, storage, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func storeConfig(ctx context.Context, storage logical.Storage, conf *models.Configuration) error {
|
||||
entry, err := logical.StorageEntryJSON(configStorageKey, conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return storage.Put(ctx, entry)
|
||||
}
|
||||
|
||||
func deprecationText(newParam, oldParam string) string {
|
||||
return fmt.Sprintf("Use %q instead. If this and %q are both specified, only %q will be used.", newParam, oldParam, newParam)
|
||||
}
|
||||
|
||||
const pathConfigSyn = `
|
||||
Provide Vault with the CA certificate used to issue all client certificates.
|
||||
`
|
||||
|
||||
const pathConfigDesc = `
|
||||
When a login is attempted using a PCF client certificate, Vault will verify
|
||||
When a login is attempted using a CF client certificate, Vault will verify
|
||||
that the client certificate was issued by the CA certificate configured here.
|
||||
Only those passing this check will be able to gain authorization.
|
||||
`
|
|
@ -1,4 +1,4 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -7,9 +7,9 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/models"
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/signatures"
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/util"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/models"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/signatures"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/util"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/cidrutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
|
@ -36,7 +36,7 @@ func (b *backend) pathLogin() *framework.Path {
|
|||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Name: "CF_INSTANCE_CERT Contents",
|
||||
},
|
||||
Description: "The full body of the file available at the CF_INSTANCE_CERT path on the PCF instance.",
|
||||
Description: "The full body of the file available at the CF_INSTANCE_CERT path on the CF instance.",
|
||||
},
|
||||
"signing_time": {
|
||||
Required: true,
|
||||
|
@ -80,7 +80,7 @@ func (b *backend) operationLoginUpdate(ctx context.Context, req *logical.Request
|
|||
return logical.ErrorResponse("'role-name' is required"), nil
|
||||
}
|
||||
|
||||
// Ensure the pcf certificate meets the role's constraints.
|
||||
// Ensure the cf certificate meets the role's constraints.
|
||||
role, err := getRole(ctx, req.Storage, roleName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -157,8 +157,8 @@ func (b *backend) operationLoginUpdate(ctx context.Context, req *logical.Request
|
|||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
// Read PCF's identity fields from the certificate.
|
||||
pcfCert, err := models.NewPCFCertificateFromx509(signingCert)
|
||||
// Read CF's identity fields from the certificate.
|
||||
cfCert, err := models.NewCFCertificateFromx509(signingCert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -167,10 +167,10 @@ func (b *backend) operationLoginUpdate(ctx context.Context, req *logical.Request
|
|||
// in an un-encoded format, as opposed to the encoded format that will appear in the Vault
|
||||
// audit logs.
|
||||
if b.Logger().IsDebug() {
|
||||
b.Logger().Debug(fmt.Sprintf("handling login attempt from %+v", pcfCert))
|
||||
b.Logger().Debug(fmt.Sprintf("handling login attempt from %+v", cfCert))
|
||||
}
|
||||
|
||||
if err := b.validate(config, role, pcfCert, req.Connection.RemoteAddr); err != nil {
|
||||
if err := b.validate(config, role, cfCert, req.Connection.RemoteAddr); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
|
@ -178,16 +178,16 @@ func (b *backend) operationLoginUpdate(ctx context.Context, req *logical.Request
|
|||
auth := &logical.Auth{
|
||||
InternalData: map[string]interface{}{
|
||||
"role": roleName,
|
||||
"instance_id": pcfCert.InstanceID,
|
||||
"ip_address": pcfCert.IPAddress,
|
||||
"instance_id": cfCert.InstanceID,
|
||||
"ip_address": cfCert.IPAddress,
|
||||
},
|
||||
DisplayName: pcfCert.InstanceID,
|
||||
DisplayName: cfCert.InstanceID,
|
||||
Alias: &logical.Alias{
|
||||
Name: pcfCert.AppID,
|
||||
Name: cfCert.AppID,
|
||||
Metadata: map[string]string{
|
||||
"org_id": pcfCert.OrgID,
|
||||
"app_id": pcfCert.AppID,
|
||||
"space_id": pcfCert.SpaceID,
|
||||
"org_id": cfCert.OrgID,
|
||||
"app_id": cfCert.AppID,
|
||||
"space_id": cfCert.SpaceID,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, data
|
|||
return nil, err
|
||||
}
|
||||
if config == nil {
|
||||
return nil, errors.New("no configuration is available for reaching the PCF API")
|
||||
return nil, errors.New("no configuration is available for reaching the CF API")
|
||||
}
|
||||
|
||||
roleName, err := getOrErr("role", req.Auth.InternalData)
|
||||
|
@ -247,8 +247,8 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, data
|
|||
}
|
||||
|
||||
// Reconstruct the certificate and ensure it still meets all constraints.
|
||||
pcfCert, err := models.NewPCFCertificate(instanceID, orgID, spaceID, appID, ipAddr)
|
||||
if err := b.validate(config, role, pcfCert, req.Connection.RemoteAddr); err != nil {
|
||||
cfCert, err := models.NewCFCertificate(instanceID, orgID, spaceID, appID, ipAddr)
|
||||
if err := b.validate(config, role, cfCert, req.Connection.RemoteAddr); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
|
@ -259,67 +259,67 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, data
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) validate(config *models.Configuration, role *models.RoleEntry, pcfCert *models.PCFCertificate, reqConnRemoteAddr string) error {
|
||||
func (b *backend) validate(config *models.Configuration, role *models.RoleEntry, cfCert *models.CFCertificate, reqConnRemoteAddr string) error {
|
||||
if !role.DisableIPMatching {
|
||||
if !matchesIPAddress(reqConnRemoteAddr, net.ParseIP(pcfCert.IPAddress)) {
|
||||
if !matchesIPAddress(reqConnRemoteAddr, net.ParseIP(cfCert.IPAddress)) {
|
||||
return errors.New("no matching IP address")
|
||||
}
|
||||
}
|
||||
if !meetsBoundConstraints(pcfCert.InstanceID, role.BoundInstanceIDs) {
|
||||
return fmt.Errorf("instance ID %s doesn't match role constraints of %s", pcfCert.InstanceID, role.BoundInstanceIDs)
|
||||
if !meetsBoundConstraints(cfCert.InstanceID, role.BoundInstanceIDs) {
|
||||
return fmt.Errorf("instance ID %s doesn't match role constraints of %s", cfCert.InstanceID, role.BoundInstanceIDs)
|
||||
}
|
||||
if !meetsBoundConstraints(pcfCert.AppID, role.BoundAppIDs) {
|
||||
return fmt.Errorf("app ID %s doesn't match role constraints of %s", pcfCert.AppID, role.BoundAppIDs)
|
||||
if !meetsBoundConstraints(cfCert.AppID, role.BoundAppIDs) {
|
||||
return fmt.Errorf("app ID %s doesn't match role constraints of %s", cfCert.AppID, role.BoundAppIDs)
|
||||
}
|
||||
if !meetsBoundConstraints(pcfCert.OrgID, role.BoundOrgIDs) {
|
||||
return fmt.Errorf("org ID %s doesn't match role constraints of %s", pcfCert.OrgID, role.BoundOrgIDs)
|
||||
if !meetsBoundConstraints(cfCert.OrgID, role.BoundOrgIDs) {
|
||||
return fmt.Errorf("org ID %s doesn't match role constraints of %s", cfCert.OrgID, role.BoundOrgIDs)
|
||||
}
|
||||
if !meetsBoundConstraints(pcfCert.SpaceID, role.BoundSpaceIDs) {
|
||||
return fmt.Errorf("space ID %s doesn't match role constraints of %s", pcfCert.SpaceID, role.BoundSpaceIDs)
|
||||
if !meetsBoundConstraints(cfCert.SpaceID, role.BoundSpaceIDs) {
|
||||
return fmt.Errorf("space ID %s doesn't match role constraints of %s", cfCert.SpaceID, role.BoundSpaceIDs)
|
||||
}
|
||||
// Use the PCF API to ensure everything still exists and to verify whatever we can.
|
||||
client, err := util.NewPCFClient(config)
|
||||
// Use the CF API to ensure everything still exists and to verify whatever we can.
|
||||
client, err := util.NewCFClient(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Here, if it were possible, we _would_ do an API call to check the instance ID,
|
||||
// but currently there's no known way to do that via the pcf API.
|
||||
// but currently there's no known way to do that via the cf API.
|
||||
|
||||
// Check everything we can using the app ID.
|
||||
app, err := client.AppByGuid(pcfCert.AppID)
|
||||
app, err := client.AppByGuid(cfCert.AppID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if app.Guid != pcfCert.AppID {
|
||||
return fmt.Errorf("cert app ID %s doesn't match API's expected one of %s", pcfCert.AppID, app.Guid)
|
||||
if app.Guid != cfCert.AppID {
|
||||
return fmt.Errorf("cert app ID %s doesn't match API's expected one of %s", cfCert.AppID, app.Guid)
|
||||
}
|
||||
if app.SpaceGuid != pcfCert.SpaceID {
|
||||
return fmt.Errorf("cert space ID %s doesn't match API's expected one of %s", pcfCert.SpaceID, app.SpaceGuid)
|
||||
if app.SpaceGuid != cfCert.SpaceID {
|
||||
return fmt.Errorf("cert space ID %s doesn't match API's expected one of %s", cfCert.SpaceID, app.SpaceGuid)
|
||||
}
|
||||
if app.Instances <= 0 {
|
||||
return errors.New("app doesn't have any live instances")
|
||||
}
|
||||
|
||||
// Check everything we can using the org ID.
|
||||
org, err := client.GetOrgByGuid(pcfCert.OrgID)
|
||||
org, err := client.GetOrgByGuid(cfCert.OrgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if org.Guid != pcfCert.OrgID {
|
||||
return fmt.Errorf("cert org ID %s doesn't match API's expected one of %s", pcfCert.OrgID, org.Guid)
|
||||
if org.Guid != cfCert.OrgID {
|
||||
return fmt.Errorf("cert org ID %s doesn't match API's expected one of %s", cfCert.OrgID, org.Guid)
|
||||
}
|
||||
|
||||
// Check everything we can using the space ID.
|
||||
space, err := client.GetSpaceByGuid(pcfCert.SpaceID)
|
||||
space, err := client.GetSpaceByGuid(cfCert.SpaceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if space.Guid != pcfCert.SpaceID {
|
||||
return fmt.Errorf("cert space ID %s doesn't match API's expected one of %s", pcfCert.SpaceID, space.Guid)
|
||||
if space.Guid != cfCert.SpaceID {
|
||||
return fmt.Errorf("cert space ID %s doesn't match API's expected one of %s", cfCert.SpaceID, space.Guid)
|
||||
}
|
||||
if space.OrganizationGuid != pcfCert.OrgID {
|
||||
return fmt.Errorf("cert org ID %s doesn't match API's expected one of %s", pcfCert.OrgID, space.OrganizationGuid)
|
||||
if space.OrganizationGuid != cfCert.OrgID {
|
||||
return fmt.Errorf("cert org ID %s doesn't match API's expected one of %s", cfCert.OrgID, space.OrganizationGuid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ Authenticates an entity with Vault.
|
|||
`
|
||||
|
||||
const pathLoginDesc = `
|
||||
Authenticate PCF entities using a client certificate issued by the
|
||||
Authenticate CF entities using a client certificate issued by the
|
||||
configured Certificate Authority, and signed by a client key belonging
|
||||
to the client certificate.
|
||||
`
|
|
@ -1,10 +1,10 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/models"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/models"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/tokenutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
|
@ -1,4 +1,4 @@
|
|||
package pcf
|
||||
package cf
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -8,18 +8,18 @@ import (
|
|||
|
||||
"github.com/cloudfoundry-community/go-cfclient"
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/hashicorp/vault-plugin-auth-pcf/models"
|
||||
"github.com/hashicorp/vault-plugin-auth-cf/models"
|
||||
)
|
||||
|
||||
const BashTimeFormat = "Mon Jan 2 15:04:05 MST 2006"
|
||||
|
||||
// NewPCFClient does some work that's needed every time we use the PCF client,
|
||||
// NewCFClient does some work that's needed every time we use the CF client,
|
||||
// namely using cleanhttp and configuring it to match the user conf.
|
||||
func NewPCFClient(config *models.Configuration) (*cfclient.Client, error) {
|
||||
func NewCFClient(config *models.Configuration) (*cfclient.Client, error) {
|
||||
clientConf := &cfclient.Config{
|
||||
ApiAddress: config.PCFAPIAddr,
|
||||
Username: config.PCFUsername,
|
||||
Password: config.PCFPassword,
|
||||
ApiAddress: config.CFAPIAddr,
|
||||
Username: config.CFUsername,
|
||||
Password: config.CFPassword,
|
||||
HttpClient: cleanhttp.DefaultClient(),
|
||||
}
|
||||
rootCAs, err := x509.SystemCertPool()
|
||||
|
@ -29,9 +29,9 @@ func NewPCFClient(config *models.Configuration) (*cfclient.Client, error) {
|
|||
if rootCAs == nil {
|
||||
rootCAs = x509.NewCertPool()
|
||||
}
|
||||
for _, certificate := range config.PCFAPICertificates {
|
||||
for _, certificate := range config.CFAPICertificates {
|
||||
if ok := rootCAs.AppendCertsFromPEM([]byte(certificate)); !ok {
|
||||
return nil, fmt.Errorf("couldn't append PCF API cert to trust: %s", certificate)
|
||||
return nil, fmt.Errorf("couldn't append CF API cert to trust: %s", certificate)
|
||||
}
|
||||
}
|
||||
tlsConfig := &tls.Config{
|
|
@ -1,29 +0,0 @@
|
|||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// Configuration is the config as it's reflected in Vault's storage system.
|
||||
type Configuration struct {
|
||||
// IdentityCACertificates are the CA certificates that should be used for verifying client certificates.
|
||||
IdentityCACertificates []string `json:"identity_ca_certificates"`
|
||||
|
||||
// IdentityCACertificates that, if presented by the PCF API, should be trusted.
|
||||
PCFAPICertificates []string `json:"pcf_api_trusted_certificates"`
|
||||
|
||||
// PCFAPIAddr is the address of PCF's API, ex: "https://api.dev.cfdev.sh" or "http://127.0.0.1:33671"
|
||||
PCFAPIAddr string `json:"pcf_api_addr"`
|
||||
|
||||
// The username for the PCF API.
|
||||
PCFUsername string `json:"pcf_username"`
|
||||
|
||||
// The password for the PCF API.
|
||||
PCFPassword string `json:"pcf_password"`
|
||||
|
||||
// The maximum seconds old a login request's signing time can be.
|
||||
// This is configurable because in some test environments we found as much as 2 hours of clock drift.
|
||||
LoginMaxSecNotBefore time.Duration `json:"login_max_seconds_not_before"`
|
||||
|
||||
// The maximum seconds ahead a login request's signing time can be.
|
||||
// This is configurable because in some test environments we found as much as 2 hours of clock drift.
|
||||
LoginMaxSecNotAfter time.Duration `json:"login_max_seconds_not_after"`
|
||||
}
|
|
@ -338,6 +338,13 @@ github.com/hashicorp/vault-plugin-auth-alicloud/tools
|
|||
github.com/hashicorp/vault-plugin-auth-azure
|
||||
# github.com/hashicorp/vault-plugin-auth-centrify v0.5.2-0.20190814210042-090ec2ed93ce
|
||||
github.com/hashicorp/vault-plugin-auth-centrify
|
||||
# github.com/hashicorp/vault-plugin-auth-cf v0.0.0-20190821162840-1c2205826fee
|
||||
github.com/hashicorp/vault-plugin-auth-cf
|
||||
github.com/hashicorp/vault-plugin-auth-cf/signatures
|
||||
github.com/hashicorp/vault-plugin-auth-cf/models
|
||||
github.com/hashicorp/vault-plugin-auth-cf/util
|
||||
github.com/hashicorp/vault-plugin-auth-cf/testing/certificates
|
||||
github.com/hashicorp/vault-plugin-auth-cf/testing/cf
|
||||
# github.com/hashicorp/vault-plugin-auth-gcp v0.5.2-0.20190814210049-1ccb3dc10102
|
||||
github.com/hashicorp/vault-plugin-auth-gcp/plugin
|
||||
github.com/hashicorp/vault-plugin-auth-gcp/plugin/cache
|
||||
|
@ -345,13 +352,6 @@ github.com/hashicorp/vault-plugin-auth-gcp/plugin/cache
|
|||
github.com/hashicorp/vault-plugin-auth-jwt
|
||||
# github.com/hashicorp/vault-plugin-auth-kubernetes v0.5.2-0.20190814210103-f64f0cb4d8cf
|
||||
github.com/hashicorp/vault-plugin-auth-kubernetes
|
||||
# github.com/hashicorp/vault-plugin-auth-pcf v0.0.0-20190814210109-476d6beb6ec0
|
||||
github.com/hashicorp/vault-plugin-auth-pcf
|
||||
github.com/hashicorp/vault-plugin-auth-pcf/signatures
|
||||
github.com/hashicorp/vault-plugin-auth-pcf/models
|
||||
github.com/hashicorp/vault-plugin-auth-pcf/util
|
||||
github.com/hashicorp/vault-plugin-auth-pcf/testing/certificates
|
||||
github.com/hashicorp/vault-plugin-auth-pcf/testing/pcf
|
||||
# github.com/hashicorp/vault-plugin-database-elasticsearch v0.0.0-20190814210117-e079e01fbb93
|
||||
github.com/hashicorp/vault-plugin-database-elasticsearch
|
||||
# github.com/hashicorp/vault-plugin-secrets-ad v0.5.3-0.20190814210122-0f2fd536b250
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
- api/auth/kubernetes/index.html
|
||||
- api/auth/ldap/index.html
|
||||
- api/auth/okta/index.html
|
||||
- api/auth/pcf/index.html
|
||||
- api/auth/cf/index.html
|
||||
- api/auth/radius/index.html
|
||||
- api/auth/cert/index.html
|
||||
- api/auth/token/index.html
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
- docs/auth/github.html
|
||||
- docs/auth/ldap.html
|
||||
- docs/auth/okta.html
|
||||
- docs/auth/pcf.html
|
||||
- docs/auth/cf.html
|
||||
- docs/auth/radius.html
|
||||
- docs/auth/cert.html
|
||||
- docs/auth/token.html
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
---
|
||||
layout: "api"
|
||||
page_title: "PCF - Auth Methods - HTTP API"
|
||||
sidebar_title: "PCF"
|
||||
sidebar_current: "api-http-auth-pcf"
|
||||
page_title: "CF - Auth Methods - HTTP API"
|
||||
sidebar_title: "CF"
|
||||
sidebar_current: "api-http-auth-cf"
|
||||
description: |-
|
||||
This is the API documentation for the Vault PCF auth method.
|
||||
This is the API documentation for the Vault CF auth method.
|
||||
---
|
||||
|
||||
# Pivotal Cloud Foundry (PCF) Auth Method (API)
|
||||
# Pivotal Cloud Foundry (CF) Auth Method (API)
|
||||
|
||||
This is the API documentation for the Vault PCF auth method. For
|
||||
general information about the usage and operation of the PCF method, please
|
||||
see the [Vault PCF method documentation](/docs/auth/pcf.html).
|
||||
This is the API documentation for the Vault CF auth method. For
|
||||
general information about the usage and operation of the CF method, please
|
||||
see the [Vault CF method documentation](/docs/auth/cf.html).
|
||||
|
||||
This documentation assumes the PCF method is mounted at the `/auth/pcf`
|
||||
This documentation assumes the CF method is mounted at the `/auth/cf`
|
||||
path in Vault. Since it is possible to enable auth methods at any location,
|
||||
please update your API calls accordingly.
|
||||
|
||||
## Create Configuration
|
||||
|
||||
Configure the root CA certificate to be used for verifying instance identity
|
||||
certificates, and configure access to the PCF API. For detailed instructions
|
||||
on how to obtain these values, please see the [Vault PCF method
|
||||
documentation](/docs/auth/pcf.html).
|
||||
certificates, and configure access to the CF API. For detailed instructions
|
||||
on how to obtain these values, please see the [Vault CF method
|
||||
documentation](/docs/auth/cf.html).
|
||||
|
||||
| Method | Path |
|
||||
| :--------|---------------------- |
|
||||
| `POST` | `/auth/pcf/config` |
|
||||
| `POST` | `/auth/cf/config` |
|
||||
|
||||
### Parameters
|
||||
|
||||
- `identity_ca_certificates` `(array: [], required)` - The root CA certificate(s)
|
||||
to be used for verifying that the `CF_INSTANCE_CERT` presented for logging in was
|
||||
issued by the proper authority.
|
||||
- `pcf_api_addr` `(string: required)`: PCF's full API address, to be used for verifying
|
||||
- `cf_api_addr` `(string: required)`: CF's full API address, to be used for verifying
|
||||
that a given `CF_INSTANCE_CERT` shows an application ID, space ID, and organization ID
|
||||
that presently exist.
|
||||
- `pcf_username` `(string: required)`: The username for authenticating to the PCF API.
|
||||
- `pcf_password` `(string: required)`: The password for authenticating to the PCF API.
|
||||
- `pcf_api_trusted_certificates` `(array: [])`: The certificate that's presented by the
|
||||
PCF API. This configures Vault to trust this certificate when making API calls, resolving
|
||||
- `cf_username` `(string: required)`: The username for authenticating to the CF API.
|
||||
- `cf_password` `(string: required)`: The password for authenticating to the CF API.
|
||||
- `cf_api_trusted_certificates` `(array: [])`: The certificate that's presented by the
|
||||
CF API. This configures Vault to trust this certificate when making API calls, resolving
|
||||
`x509: certificate signed by unknown authority` errors.
|
||||
- `login_max_seconds_not_before` `(int: 300)`: The maximum number of seconds in the past when a
|
||||
signature could have been created. The lower the value, the lower the risk of replay
|
||||
|
@ -53,10 +53,10 @@ the lower the risk of replay attacks.
|
|||
```json
|
||||
{
|
||||
"identity_ca_certificates": ["-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+.......ZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----"],
|
||||
"pcf_api_addr": "https://api.sys.somewhere.cf-app.com",
|
||||
"pcf_username": "vault",
|
||||
"pcf_password": "pa55w0rd",
|
||||
"pcf_api_trusted_certificates": ["-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+.......ZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----"],
|
||||
"cf_api_addr": "https://api.sys.somewhere.cf-app.com",
|
||||
"cf_username": "vault",
|
||||
"cf_password": "pa55w0rd",
|
||||
"cf_api_trusted_certificates": ["-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+.......ZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----"],
|
||||
"login_max_seconds_not_before": 5,
|
||||
"login_max_seconds_not_after": 1
|
||||
}
|
||||
|
@ -69,23 +69,23 @@ $ curl \
|
|||
--header "X-Vault-Token: ..." \
|
||||
--request POST \
|
||||
--data @payload.json \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/config
|
||||
http://127.0.0.1:8200/v1/auth/cf/config
|
||||
```
|
||||
|
||||
## Read Config
|
||||
|
||||
Returns the present PCF configuration.
|
||||
Returns the present CF configuration.
|
||||
|
||||
| Method | Path |
|
||||
| :--------|---------------------- |
|
||||
| `GET` | `/auth/pcf/config` |
|
||||
| `GET` | `/auth/cf/config` |
|
||||
|
||||
### Sample Request
|
||||
|
||||
```
|
||||
$ curl \
|
||||
--header "X-Vault-Token: ..." \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/config
|
||||
http://127.0.0.1:8200/v1/auth/cf/config
|
||||
```
|
||||
|
||||
### Sample Response
|
||||
|
@ -93,9 +93,9 @@ $ curl \
|
|||
```json
|
||||
{
|
||||
"identity_ca_certificates": ["-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+.......ZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----"],
|
||||
"pcf_api_addr": "https://api.sys.somewhere.cf-app.com",
|
||||
"pcf_username": "vault",
|
||||
"pcf_api_trusted_certificates": ["-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+.......ZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----"],
|
||||
"cf_api_addr": "https://api.sys.somewhere.cf-app.com",
|
||||
"cf_username": "vault",
|
||||
"cf_api_trusted_certificates": ["-----BEGIN CERTIFICATE-----\nMIIEtzCCA5+.......ZRtAfQ6r\nwlW975rYa1ZqEdA=\n-----END CERTIFICATE-----"],
|
||||
"login_max_seconds_not_before": 5,
|
||||
"login_max_seconds_not_after": 1
|
||||
}
|
||||
|
@ -103,11 +103,11 @@ $ curl \
|
|||
|
||||
## Delete Config
|
||||
|
||||
Deletes the present PCF configuration.
|
||||
Deletes the present CF configuration.
|
||||
|
||||
| Method | Path |
|
||||
| :--------|---------------------- |
|
||||
| `DELETE` | `/auth/pcf/config` |
|
||||
| `DELETE` | `/auth/cf/config` |
|
||||
|
||||
### Sample Request
|
||||
|
||||
|
@ -115,13 +115,13 @@ Deletes the present PCF configuration.
|
|||
$ curl \
|
||||
--header "X-Vault-Token: ..." \
|
||||
--request DELETE \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/config
|
||||
http://127.0.0.1:8200/v1/auth/cf/config
|
||||
```
|
||||
|
||||
## Create Role
|
||||
|
||||
Create a role in Vault granting a particular level of access to a particular group
|
||||
of PCF instances. We recommend using the PCF API or the CF CLI to gain the IDs you
|
||||
of CF instances. We recommend using the CF API or the CF CLI to gain the IDs you
|
||||
wish to target.
|
||||
|
||||
If you list no `bound` parameters, then any entity with a valid
|
||||
|
@ -130,7 +130,7 @@ will be able to authenticate against this role.
|
|||
|
||||
| Method | Path |
|
||||
| :--------|----------------------- |
|
||||
| `POST` | `/auth/pcf/roles/:role`|
|
||||
| `POST` | `/auth/cf/roles/:role`|
|
||||
|
||||
### Parameters
|
||||
|
||||
|
@ -144,7 +144,7 @@ an instance must be a member of to qualify as a member of this role.
|
|||
- `bound_instance_ids` `(array: [])` - An optional list of instance IDs
|
||||
an instance must be a member of to qualify as a member of this role. Please note that
|
||||
every time you use `cf push` on an app, its instance ID changes. Also, instance IDs
|
||||
are not verifiable as being presently alive using the PCF API. Thus, we recommend against
|
||||
are not verifiable as being presently alive using the CF API. Thus, we recommend against
|
||||
using this setting for most use cases.
|
||||
- `disable_ip_matching` `(bool: false)` - If set to true, disables the default behavior
|
||||
that logging in must be performed from an acceptable IP address described by the
|
||||
|
@ -176,23 +176,23 @@ $ curl \
|
|||
--header "X-Vault-Token: ..." \
|
||||
--request POST \
|
||||
--data @payload.json \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/roles/:role
|
||||
http://127.0.0.1:8200/v1/auth/cf/roles/:role
|
||||
```
|
||||
|
||||
## Read Role
|
||||
|
||||
Returns a PCF role.
|
||||
Returns a CF role.
|
||||
|
||||
| Method | Path |
|
||||
| :--------|----------------------- |
|
||||
| `GET` | `/auth/pcf/roles/:role`|
|
||||
| `GET` | `/auth/cf/roles/:role`|
|
||||
|
||||
### Sample Request
|
||||
|
||||
```
|
||||
$ curl \
|
||||
--header "X-Vault-Token: ..." \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/roles/:role
|
||||
http://127.0.0.1:8200/v1/auth/cf/roles/:role
|
||||
```
|
||||
|
||||
### Sample Response
|
||||
|
@ -213,11 +213,11 @@ $ curl \
|
|||
|
||||
## Delete Role
|
||||
|
||||
Deletes a PCF role.
|
||||
Deletes a CF role.
|
||||
|
||||
| Method | Path |
|
||||
| :--------|----------------------- |
|
||||
| `DELETE` | `/auth/pcf/roles/:role`|
|
||||
| `DELETE` | `/auth/cf/roles/:role`|
|
||||
|
||||
### Sample Request
|
||||
|
||||
|
@ -225,16 +225,16 @@ Deletes a PCF role.
|
|||
$ curl \
|
||||
--header "X-Vault-Token: ..." \
|
||||
--request DELETE \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/roles/:role
|
||||
http://127.0.0.1:8200/v1/auth/cf/roles/:role
|
||||
```
|
||||
|
||||
## List Roles
|
||||
|
||||
Returns a PCF role.
|
||||
Returns a CF role.
|
||||
|
||||
| Method | Path |
|
||||
| :--------|----------------------- |
|
||||
| `LIST` | `/auth/pcf/roles` |
|
||||
| `LIST` | `/auth/cf/roles` |
|
||||
|
||||
### Sample Request
|
||||
|
||||
|
@ -242,7 +242,7 @@ Returns a PCF role.
|
|||
$ curl \
|
||||
--header "X-Vault-Token: ..." \
|
||||
--request LIST
|
||||
http://127.0.0.1:8200/v1/auth/pcf/roles
|
||||
http://127.0.0.1:8200/v1/auth/cf/roles
|
||||
```
|
||||
|
||||
### Sample Response
|
||||
|
@ -260,12 +260,12 @@ $ curl \
|
|||
|
||||
## Login
|
||||
|
||||
Log in to PCF.
|
||||
Log in to CF.
|
||||
|
||||
Vault provides both an agent and a CLI tool for logging in that
|
||||
eliminates the need to build a signature yourself. However, if you do wish to
|
||||
build the signature, its signing algorithm is viewable [here](https://github.com/hashicorp/vault-plugin-auth-pcf/tree/master/signatures).
|
||||
The [plugin repo](https://github.com/hashicorp/vault-plugin-auth-pcf) also contains
|
||||
build the signature, its signing algorithm is viewable [here](https://github.com/hashicorp/vault-plugin-auth-cf/tree/master/signatures).
|
||||
The [plugin repo](https://github.com/hashicorp/vault-plugin-auth-cf) also contains
|
||||
a command-line tool (`generate-signature`) that can be compiled as a binary for generating a signature,
|
||||
and a test that outputs steps in generating the signature so they can be duplicated.
|
||||
|
||||
|
@ -284,7 +284,7 @@ rsa.SignPSS(rand.Reader, rsaPrivateKey, crypto.SHA256, checksum, nil)
|
|||
|
||||
| Method | Path |
|
||||
| :--------|----------------------- |
|
||||
| `POST` | `/auth/pcf/login` |
|
||||
| `POST` | `/auth/cf/login` |
|
||||
|
||||
### Parameters
|
||||
|
||||
|
@ -313,7 +313,7 @@ $ curl \
|
|||
--header "X-Vault-Token: ..." \
|
||||
--request POST \
|
||||
--data @payload.json \
|
||||
http://127.0.0.1:8200/v1/auth/pcf/login
|
||||
http://127.0.0.1:8200/v1/auth/cf/login
|
||||
```
|
||||
|
||||
### Sample Response
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "Vault Agent Auto-Auth CF Method"
|
||||
sidebar_title: "CF"
|
||||
sidebar_current: "docs-agent-autoauth-methods-cf"
|
||||
description: |-
|
||||
CF Method for Vault Agent Auto-Auth
|
||||
---
|
||||
|
||||
# Vault Agent Auto-Auth CF Method
|
||||
|
||||
The `cf` method performs authentication against the [CF Auth
|
||||
method] (https://www.vaultproject.io/docs/auth/cf.html).
|
||||
|
||||
## Credentials
|
||||
|
||||
The Vault agent will use the `CF_INSTANCE_CERT` and `CF_INSTANCE_KEY` env variables to
|
||||
construct a valid login call for CF.
|
||||
|
||||
## Configuration
|
||||
|
||||
- `role` `(string: required)` - The role to authenticate against on Vault.
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "Vault Agent Auto-Auth PCF Method"
|
||||
sidebar_title: "PCF"
|
||||
sidebar_current: "docs-agent-autoauth-methods-pcf"
|
||||
description: |-
|
||||
PCF Method for Vault Agent Auto-Auth
|
||||
---
|
||||
|
||||
# Vault Agent Auto-Auth PCF Method
|
||||
|
||||
The `pcf` method performs authentication against the [PCF Auth
|
||||
method] (https://www.vaultproject.io/docs/auth/pcf.html).
|
||||
|
||||
## Credentials
|
||||
|
||||
The Vault agent will use the `CF_INSTANCE_CERT` and `CF_INSTANCE_KEY` env variables to
|
||||
construct a valid login call for PCF.
|
||||
|
||||
## Configuration
|
||||
|
||||
- `role` `(string: required)` - The role to authenticate against on Vault.
|
|
@ -1,16 +1,16 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "PCF - Auth Methods"
|
||||
sidebar_title: "PCF"
|
||||
sidebar_current: "docs-auth-pcf"
|
||||
page_title: "CF - Auth Methods"
|
||||
sidebar_title: "CF"
|
||||
sidebar_current: "docs-auth-cf"
|
||||
description: |-
|
||||
The pcf auth method allows automated authentication of PCF instances.
|
||||
The cf auth method allows automated authentication of CF instances.
|
||||
---
|
||||
|
||||
# Pivotal Cloud Foundry (PCF) Auth Method
|
||||
# Cloud Foundry (CF) Auth Method
|
||||
|
||||
The `pcf` auth method provides an automated mechanism to retrieve a Vault token
|
||||
for PCF instances. It leverages PCF's [App and Container Identity Assurance](https://content.pivotal.io/blog/new-in-pcf-2-1-app-container-identity-assurance-via-automatic-cert-rotation).
|
||||
The `cf` auth method provides an automated mechanism to retrieve a Vault token
|
||||
for CF instances. It leverages CF's [App and Container Identity Assurance](https://content.pivotal.io/blog/new-in-pcf-2-1-app-container-identity-assurance-via-automatic-cert-rotation).
|
||||
At a high level, this works as follows:
|
||||
|
||||
1. You construct a request to Vault including your `CF_INSTANCE_CERT`, signed by your `CF_INSTANCE_KEY`.
|
||||
|
@ -22,8 +22,8 @@ At a high level, this works as follows:
|
|||
|
||||
## Known Risks
|
||||
|
||||
This authentication engine uses PCF's instance identity service to authenticate users to Vault. Because
|
||||
PCF makes its CA certificate and private key available to certain users at any time, it's possible for
|
||||
This authentication engine uses CF's instance identity service to authenticate users to Vault. Because
|
||||
CF makes its CA certificate and private key available to certain users at any time, it's possible for
|
||||
someone with access to them to self-issue identity certificates that meet the criteria for a Vault role,
|
||||
allowing them to gain unintended access to Vault.
|
||||
|
||||
|
@ -38,8 +38,8 @@ system, or through carefully limiting the users who can access CredHub.
|
|||
|
||||
### Preparing to Configure the Plugin
|
||||
|
||||
To configure this plugin, you'll need to gather the CA certificate that PCF uses to issue each `CF_INSTANCE_CERT`,
|
||||
and you'll need to configure it to access the PCF API.
|
||||
To configure this plugin, you'll need to gather the CA certificate that CF uses to issue each `CF_INSTANCE_CERT`,
|
||||
and you'll need to configure it to access the CF API.
|
||||
|
||||
To gain your instance identity CA certificate, in the [cf dev](https://github.com/cloudfoundry-incubator/cfdev)
|
||||
environment it can be found using:
|
||||
|
@ -73,7 +73,7 @@ Log into CredHub with the credentials you obtained earlier:
|
|||
$ credhub login --client-name=director_to_credhub --client-secret=some-secret
|
||||
```
|
||||
|
||||
And view the root certificate PCF uses to issue instance identity certificates:
|
||||
And view the root certificate CF uses to issue instance identity certificates:
|
||||
|
||||
```
|
||||
$ credhub get -n /cf/diego-instance-identity-root-ca
|
||||
|
@ -171,11 +171,11 @@ Certificate:
|
|||
60:b2:69:7c
|
||||
```
|
||||
|
||||
You will also need to configure access to the PCF API. To prepare for this, we will now
|
||||
You will also need to configure access to the CF API. To prepare for this, we will now
|
||||
use the [cf](https://docs.cloudfoundry.org/cf-cli/install-go-cli.html) command-line tool.
|
||||
|
||||
First, while in the directory containing the `metadata` file you used earlier to authenticate
|
||||
to PCF, run `$ pcf target`. This points the `cf` tool at the same place as the `pcf` tool. Next,
|
||||
to CF, run `$ pcf target`. This points the `cf` tool at the same place as the `pcf` tool. Next,
|
||||
run `$ cf api` to view the API endpoint that Vault will use.
|
||||
|
||||
Next, configure a user for Vault to use. This plugin was tested with Org Manager level
|
||||
|
@ -203,7 +203,7 @@ with an error like:
|
|||
x509: certificate signed by unknown authority
|
||||
```
|
||||
|
||||
If you encounter this error, you will need to first gain a copy of the certificate that PCF
|
||||
If you encounter this error, you will need to first gain a copy of the certificate that CF
|
||||
is using for the API via:
|
||||
|
||||
```
|
||||
|
@ -219,62 +219,62 @@ $ openssl s_client -showcerts -servername api.sys.somewhere.cf-app.com -connect
|
|||
Part of the response will contain a certificate, which you'll need to copy and paste to
|
||||
a well-formatted local file. Please see `ca.crt` above for an example of how the certificate
|
||||
should look, and how to verify it can be parsed using `openssl`. The walkthrough below presumes
|
||||
you name this file `pcfapi.crt`.
|
||||
you name this file `cfapi.crt`.
|
||||
|
||||
### Walkthrough
|
||||
|
||||
After obtaining the information described above, a Vault operator will configure the PCF auth method
|
||||
After obtaining the information described above, a Vault operator will configure the CF auth method
|
||||
like so:
|
||||
|
||||
```
|
||||
$ vault auth enable pcf
|
||||
$ vault auth enable cf
|
||||
|
||||
$ vault write auth/pcf/config \
|
||||
$ vault write auth/cf/config \
|
||||
identity_ca_certificates=@ca.crt \
|
||||
pcf_api_addr=https://api.dev.cfdev.sh \
|
||||
pcf_username=vault \
|
||||
pcf_password=pa55w0rd \
|
||||
pcf_api_trusted_certificates=@pcfapi.crt
|
||||
cf_api_addr=https://api.dev.cfdev.sh \
|
||||
cf_username=vault \
|
||||
cf_password=pa55w0rd \
|
||||
cf_api_trusted_certificates=@cfapi.crt
|
||||
|
||||
$ vault write auth/pcf/roles/my-role \
|
||||
$ vault write auth/cf/roles/my-role \
|
||||
bound_application_ids=2d3e834a-3a25-4591-974c-fa5626d5d0a1 \
|
||||
bound_space_ids=3d2eba6b-ef19-44d5-91dd-1975b0db5cc9 \
|
||||
bound_organization_ids=34a878d0-c2f9-4521-ba73-a9f664e82c7bf \
|
||||
policies=my-policy
|
||||
```
|
||||
|
||||
Once configured, from a PCF instance containing real values for the `CF_INSTANCE_CERT` and
|
||||
Once configured, from a CF instance containing real values for the `CF_INSTANCE_CERT` and
|
||||
`CF_INSTANCE_KEY`, login can be performed using:
|
||||
|
||||
```
|
||||
$ vault login -method=pcf role=test-role
|
||||
$ vault login -method=cf role=test-role
|
||||
```
|
||||
|
||||
For PCF, we do also offer an agent that, once configured, can be used to obtain a Vault token on
|
||||
For CF, we do also offer an agent that, once configured, can be used to obtain a Vault token on
|
||||
your behalf.
|
||||
|
||||
### Maintenance
|
||||
|
||||
In testing we found that PCF instance identity CA certificates were set to expire in 3 years. Some
|
||||
PCF docs indicate they expire every 4 years. However long they last, at some point you may need
|
||||
In testing we found that CF instance identity CA certificates were set to expire in 3 years. Some
|
||||
CF docs indicate they expire every 4 years. However long they last, at some point you may need
|
||||
to add another CA certificate - one that's soon to expire, and one that is currently or soon-to-be
|
||||
valid.
|
||||
|
||||
```
|
||||
$ CURRENT=$(cat /path/to/current-ca.crt)
|
||||
$ FUTURE=$(cat /path/to/future-ca.crt)
|
||||
$ vault write auth/vault-plugin-auth-pcf/config identity_ca_certificates="$CURRENT,$FUTURE"
|
||||
$ vault write auth/vault-plugin-auth-cf/config identity_ca_certificates="$CURRENT,$FUTURE"
|
||||
```
|
||||
|
||||
If Vault receives a `CF_INSTANCE_CERT` matching _any_ of the `identity_ca_certificates`,
|
||||
the instance cert will be considered valid.
|
||||
|
||||
A similar approach can be taken to update the `pcf_api_trusted_certificates`.
|
||||
A similar approach can be taken to update the `cf_api_trusted_certificates`.
|
||||
|
||||
### Troubleshooting At-A-Glance
|
||||
|
||||
If you receive an error containing `x509: certificate signed by unknown authority`, set
|
||||
`pcf_api_trusted_certificates` as described above.
|
||||
`cf_api_trusted_certificates` as described above.
|
||||
|
||||
If you're unable to authenticate using the `CF_INSTANCE_CERT`, first obtain a current copy
|
||||
of your `CF_INSTANCE_CERT` and copy it to your local environment. Then divide it into two
|
||||
|
@ -298,5 +298,5 @@ match the certificates you're checking.
|
|||
|
||||
## API
|
||||
|
||||
The PCF auth method has a full HTTP API. Please see the [PCF Auth API](/api/auth/pcf/index.html)
|
||||
The CF auth method has a full HTTP API. Please see the [CF Auth API](/api/auth/cf/index.html)
|
||||
for more details.
|
|
@ -72,13 +72,13 @@
|
|||
{ category: 'alicloud' },
|
||||
{ category: 'aws' },
|
||||
{ category: 'azure' },
|
||||
{ category: 'cf' },
|
||||
{ category: 'github' },
|
||||
{ category: 'gcp' },
|
||||
{ category: 'jwt' },
|
||||
{ category: 'kubernetes' },
|
||||
{ category: 'ldap' },
|
||||
{ category: 'okta' },
|
||||
{ category: 'pcf' },
|
||||
{ category: 'radius' },
|
||||
{ category: 'cert' },
|
||||
{ category: 'token' },
|
||||
|
|
|
@ -199,10 +199,10 @@
|
|||
'aws',
|
||||
'azure',
|
||||
'cert',
|
||||
'cf',
|
||||
'gcp',
|
||||
'jwt',
|
||||
'kubernetes',
|
||||
'pcf'
|
||||
'kubernetes'
|
||||
]
|
||||
}, {
|
||||
category: 'sinks',
|
||||
|
@ -273,13 +273,13 @@
|
|||
'alicloud',
|
||||
'aws',
|
||||
'azure',
|
||||
'cf',
|
||||
'gcp',
|
||||
'jwt',
|
||||
'kubernetes',
|
||||
'github',
|
||||
'ldap',
|
||||
'okta',
|
||||
'pcf',
|
||||
'radius',
|
||||
'cert',
|
||||
'token',
|
||||
|
|
Loading…
Reference in New Issue