// Verify that we are able to update from non-salted (<0.2) to // using a Salt for the paths func TestBackend_upgradeToSalted(t *testing.T) { inm := new(logical.InmemStorage) // Create some fake keys se, _ := logical.StorageEntryJSON("struct/map/app-id/foo", map[string]string{"value": "test"}) inm.Put(se) se, _ = logical.StorageEntryJSON("struct/map/user-id/bar", map[string]string{"value": "foo"}) inm.Put(se) // Initialize the backend, this should do the automatic upgrade conf := &logical.BackendConfig{ StorageView: inm, } backend, err := Factory(conf) if err != nil { t.Fatalf("err: %v", err) } // Check the keys have been upgraded out, err := inm.Get("struct/map/app-id/foo") if err != nil { t.Fatalf("err: %v", err) } if out != nil { t.Fatalf("unexpected key") } out, err = inm.Get("struct/map/user-id/bar") if err != nil { t.Fatalf("err: %v", err) } if out != nil { t.Fatalf("unexpected key") } // Backend should still be able to resolve req := logical.TestRequest(t, logical.ReadOperation, "map/app-id/foo") req.Storage = inm resp, err := backend.HandleRequest(req) if err != nil { t.Fatalf("err: %v", err) } if resp.Data["value"] != "test" { t.Fatalf("bad: %#v", resp) } req = logical.TestRequest(t, logical.ReadOperation, "map/user-id/bar") req.Storage = inm resp, err = backend.HandleRequest(req) if err != nil { t.Fatalf("err: %v", err) } if resp.Data["value"] != "foo" { t.Fatalf("bad: %#v", resp) } }
func pathConfigWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { conf := config{ Org: data.Get("organization").(string), } baseURL := data.Get("base_url").(string) if len(baseURL) != 0 { _, err := url.Parse(baseURL) if err != nil { return logical.ErrorResponse(fmt.Sprintf("Error parsing given base_url: %s", err)), nil } conf.BaseURL = baseURL } entry, err := logical.StorageEntryJSON("config", conf) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
// SetPolicy is used to create or update the given policy func (ps *PolicyStore) SetPolicy(p *Policy) error { defer metrics.MeasureSince([]string{"policy", "set_policy"}, time.Now()) if p.Name == "root" { return fmt.Errorf("cannot update root policy") } if p.Name == "" { return fmt.Errorf("policy name missing") } // Create the entry entry, err := logical.StorageEntryJSON(p.Name, &PolicyEntry{ Version: 2, Raw: p.Raw, }) if err != nil { return fmt.Errorf("failed to create entry: %v", err) } if err := ps.view.Put(entry); err != nil { return fmt.Errorf("failed to persist policy: %v", err) } // Update the LRU cache ps.lru.Add(p.Name, p) return nil }
func (b *backend) pathConfigLeaseWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { ttlRaw := d.Get("ttl").(string) ttlMaxRaw := d.Get("max_ttl").(string) if len(ttlMaxRaw) == 0 { ttlMaxRaw = d.Get("ttl_max").(string) } ttl, err := time.ParseDuration(ttlRaw) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Invalid ttl: %s", err)), nil } ttlMax, err := time.ParseDuration(ttlMaxRaw) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Invalid max_ttl: %s", err)), nil } // Store it entry, err := logical.StorageEntryJSON("config/lease", &configLease{ TTL: ttl, TTLMax: ttlMax, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathRoleUpdate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name, err := validateName(data) if err != nil { return nil, err } tags := data.Get("tags").(string) rawVHosts := data.Get("vhosts").(string) var vhosts map[string]vhostPermission if len(rawVHosts) > 0 { err := json.Unmarshal([]byte(rawVHosts), &vhosts) if err != nil { return logical.ErrorResponse(fmt.Sprintf("failed to unmarshal vhosts: %s", err)), nil } } // Store it entry, err := logical.StorageEntryJSON("role/"+name, &roleEntry{ Tags: tags, VHosts: vhosts, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathRoleCreate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("name").(string) sql := data.Get("sql").(string) // Get our connection db, err := b.DB(req.Storage) if err != nil { return nil, err } // Test the query by trying to prepare it, HANA don't support grant if user not exist query := SplitSQL(sql)[0] stmt, err := db.Prepare(Query(query, map[string]string{ "name": "VAULT_TEST_ACCOUNT", "password": "******", })) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error testing query: %s", err)), nil } stmt.Close() // Store it entry, err := logical.StorageEntryJSON("role/"+name, &roleEntry{ SQL: sql, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
// createSecretIDAccessorEntry creates an identifier for the SecretID. A storage index, // mapping the accessor to the SecretID is also created. This method should // be called when the lock for the corresponding SecretID is held. func (b *backend) createSecretIDAccessorEntry(s logical.Storage, entry *secretIDStorageEntry, secretIDHMAC string) error { // Create a random accessor accessorUUID, err := uuid.GenerateUUID() if err != nil { return err } entry.SecretIDAccessor = accessorUUID // Create index entry, mapping the accessor to the token ID entryIndex := "accessor/" + b.salt.SaltID(entry.SecretIDAccessor) accessorLock := b.secretIDAccessorLock(accessorUUID) accessorLock.Lock() defer accessorLock.Unlock() if entry, err := logical.StorageEntryJSON(entryIndex, &secretIDAccessorStorageEntry{ SecretIDHMAC: secretIDHMAC, }); err != nil { return err } else if err = s.Put(entry); err != nil { return fmt.Errorf("failed to persist accessor index entry: %s", err) } return nil }
// Generates an UUID OTP and creates an entry for the same in storage backend with its salted string. func (b *backend) GenerateOTPCredential(req *logical.Request, username, ip string) (string, error) { otp, otpSalted := b.GenerateSaltedOTP() // Check if there is an entry already created for the newly generated OTP. entry, err := b.getOTP(req.Storage, otpSalted) // If entry already exists for the OTP, make sure that new OTP is not // replacing an existing one by recreating new ones until an unused // OTP is generated. It is very unlikely that this is the case and this // code is just for safety. for err == nil && entry != nil { otp, otpSalted = b.GenerateSaltedOTP() entry, err = b.getOTP(req.Storage, otpSalted) if err != nil { return "", err } } // Store an entry for the salt of OTP. newEntry, err := logical.StorageEntryJSON("otp/"+otpSalted, sshOTP{ Username: username, IP: ip, }) if err != nil { return "", err } if err := req.Storage.Put(newEntry); err != nil { return "", err } return otp, nil }
func (b *backend) pathLeaseWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { leaseRaw := d.Get("lease").(string) leaseMaxRaw := d.Get("lease_max").(string) lease, err := time.ParseDuration(leaseRaw) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Invalid lease: %s", err)), nil } leaseMax, err := time.ParseDuration(leaseMaxRaw) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Invalid lease: %s", err)), nil } // Store it entry, err := logical.StorageEntryJSON("config/lease", &configLease{ Lease: lease, LeaseMax: leaseMax, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
// Registers a new role with the backend func (b *backend) pathRoleUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { name := d.Get("name").(string) if name == "" { return logical.ErrorResponse("missing name"), nil } tags := d.Get("tags").(string) rawVHosts := d.Get("vhosts").(string) if tags == "" && rawVHosts == "" { return logical.ErrorResponse("both tags and vhosts not specified"), nil } var vhosts map[string]vhostPermission if len(rawVHosts) > 0 { err := json.Unmarshal([]byte(rawVHosts), &vhosts) if err != nil { return logical.ErrorResponse(fmt.Sprintf("failed to unmarshal vhosts: %s", err)), nil } } // Store it entry, err := logical.StorageEntryJSON("role/"+name, &roleEntry{ Tags: tags, VHosts: vhosts, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathKeysWrite(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { keyName := d.Get("key_name").(string) if keyName == "" { return logical.ErrorResponse("Missing key_name"), nil } keyString := d.Get("key").(string) // Check if the key provided is infact a private key signer, err := ssh.ParsePrivateKey([]byte(keyString)) if err != nil || signer == nil { return logical.ErrorResponse("Invalid key"), nil } if keyString == "" { return logical.ErrorResponse("Missing key"), nil } keyPath := fmt.Sprintf("keys/%s", keyName) // Store the key entry, err := logical.StorageEntryJSON(keyPath, map[string]interface{}{ "key": keyString, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathRoleCreate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("name").(string) creationCQL := data.Get("creation_cql").(string) rollbackCQL := data.Get("rollback_cql").(string) leaseRaw := data.Get("lease").(string) lease, err := time.ParseDuration(leaseRaw) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error parsing lease value of %s: %s", leaseRaw, err)), nil } entry := &roleEntry{ Lease: lease, CreationCQL: creationCQL, RollbackCQL: rollbackCQL, } // Store it entryJSON, err := logical.StorageEntryJSON("role/"+name, entry) if err != nil { return nil, err } if err := req.Storage.Put(entryJSON); err != nil { return nil, err } return nil, nil }
func (b *backend) pathConnectionWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { connValue := data.Get("value").(string) connURL := data.Get("connection_url").(string) if connURL == "" { if connValue == "" { return logical.ErrorResponse("connection_url parameter must be supplied"), nil } else { connURL = connValue } } maxOpenConns := data.Get("max_open_connections").(int) if maxOpenConns == 0 { maxOpenConns = 2 } maxIdleConns := data.Get("max_idle_connections").(int) if maxIdleConns == 0 { maxIdleConns = maxOpenConns } if maxIdleConns > maxOpenConns { maxIdleConns = maxOpenConns } // Don't check the connection_url if verification is disabled verifyConnection := data.Get("verify_connection").(bool) if verifyConnection { // Verify the string db, err := sql.Open("postgres", connURL) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error validating connection info: %s", err)), nil } defer db.Close() if err := db.Ping(); err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error validating connection info: %s", err)), nil } } // Store it entry, err := logical.StorageEntryJSON("config/connection", connectionConfig{ ConnectionString: connValue, ConnectionURL: connURL, MaxOpenConnections: maxOpenConns, MaxIdleConnections: maxIdleConns, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } // Reset the DB connection b.ResetDB() return nil, nil }
func (b *backend) pathConfigTidyRoletagBlacklistCreateUpdate(req *logical.Request, data *framework.FieldData) (*logical.Response, error) { b.configMutex.Lock() defer b.configMutex.Unlock() configEntry, err := b.nonLockedConfigTidyRoleTags(req.Storage) if err != nil { return nil, err } if configEntry == nil { configEntry = &tidyBlacklistRoleTagConfig{} } safetyBufferInt, ok := data.GetOk("safety_buffer") if ok { configEntry.SafetyBuffer = safetyBufferInt.(int) } else if req.Operation == logical.CreateOperation { configEntry.SafetyBuffer = data.Get("safety_buffer").(int) } disablePeriodicTidyBool, ok := data.GetOk("disable_periodic_tidy") if ok { configEntry.DisablePeriodicTidy = disablePeriodicTidyBool.(bool) } else if req.Operation == logical.CreateOperation { configEntry.DisablePeriodicTidy = data.Get("disable_periodic_tidy").(bool) } entry, err := logical.StorageEntryJSON(roletagBlacklistConfigPath, configEntry) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathUserWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { name := strings.ToLower(d.Get("name").(string)) password := d.Get("password").(string) policies := strings.Split(d.Get("policies").(string), ",") for i, p := range policies { policies[i] = strings.TrimSpace(p) } // Generate a hash of the password hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return nil, err } // Store it entry, err := logical.StorageEntryJSON("user/"+name, &UserEntry{ PasswordHash: hash, Policies: policies, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
// pathConfigCertificateCreateUpdate is used to register an AWS Public Key that is // used to verify the PKCS#7 signature of the instance identity document. func (b *backend) pathConfigCertificateCreateUpdate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { certName := data.Get("cert_name").(string) if certName == "" { return logical.ErrorResponse("missing cert_name"), nil } b.configMutex.Lock() defer b.configMutex.Unlock() // Check if there is already a certificate entry registered. certEntry, err := b.nonLockedAWSPublicCertificateEntry(req.Storage, certName) if err != nil { return nil, err } if certEntry == nil { certEntry = &awsPublicCert{} } // Check if the value is provided by the client. certStrData, ok := data.GetOk("aws_public_cert") if ok { if certBytes, err := base64.StdEncoding.DecodeString(certStrData.(string)); err == nil { certEntry.AWSPublicCert = string(certBytes) } else { certEntry.AWSPublicCert = certStrData.(string) } } else { // aws_public_cert should be supplied for both create and update operations. // If it is not provided, throw an error. return logical.ErrorResponse("missing aws_public_cert"), nil } // If explicitly set to empty string, error out. if certEntry.AWSPublicCert == "" { return logical.ErrorResponse("invalid aws_public_cert"), nil } // Verify the certificate by decoding it and parsing it. publicCert, err := decodePEMAndParseCertificate(certEntry.AWSPublicCert) if err != nil { return nil, err } if publicCert == nil { return logical.ErrorResponse("invalid certificate; failed to decode and parse certificate"), nil } // Ensure that we have not // If none of the checks fail, save the provided certificate. entry, err := logical.StorageEntryJSON("config/certificate/"+certName, certEntry) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func pathRolesWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { name := d.Get("name").(string) policyRaw, err := base64.StdEncoding.DecodeString(d.Get("policy").(string)) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error decoding policy base64: %s", err)), nil } lease, err := time.ParseDuration(d.Get("lease").(string)) if err != nil || lease == time.Duration(0) { lease = DefaultLeaseDuration } entry, err := logical.StorageEntryJSON("policy/"+name, roleConfig{ Policy: string(policyRaw), Lease: lease, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathConnectionWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { connString := data.Get("value").(string) // Verify the string db, err := sql.Open("postgres", connString) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error validating connection info: %s", err)), nil } defer db.Close() if err := db.Ping(); err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error validating connection info: %s", err)), nil } // Store it entry, err := logical.StorageEntryJSON("config/connection", connString) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } // Reset the DB connection b.ResetDB() return nil, nil }
func (b *backend) pathGenerateIntermediate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { var err error exported, format, role, errorResp := b.getGenerationParams(data) if errorResp != nil { return errorResp, nil } var resp *logical.Response parsedBundle, err := generateIntermediateCSR(b, role, nil, req, data) if err != nil { switch err.(type) { case certutil.UserError: return logical.ErrorResponse(err.Error()), nil case certutil.InternalError: return nil, err } } csrb, err := parsedBundle.ToCSRBundle() if err != nil { return nil, fmt.Errorf("Error converting raw CSR bundle to CSR bundle: %s", err) } resp = &logical.Response{ Data: map[string]interface{}{}, } switch format { case "pem": resp.Data["csr"] = csrb.CSR if exported { resp.Data["private_key"] = csrb.PrivateKey resp.Data["private_key_type"] = csrb.PrivateKeyType } case "der": resp.Data["csr"] = base64.StdEncoding.EncodeToString(parsedBundle.CSRBytes) if exported { resp.Data["private_key"] = base64.StdEncoding.EncodeToString(parsedBundle.PrivateKeyBytes) resp.Data["private_key_type"] = csrb.PrivateKeyType } } cb := &certutil.CertBundle{} cb.PrivateKey = csrb.PrivateKey cb.PrivateKeyType = csrb.PrivateKeyType entry, err := logical.StorageEntryJSON("config/ca_bundle", cb) if err != nil { return nil, err } err = req.Storage.Put(entry) if err != nil { return nil, err } return resp, nil }
func (b *backend) setUser(s logical.Storage, username string, userEntry *UserEntry) error { entry, err := logical.StorageEntryJSON("user/"+username, userEntry) if err != nil { return err } return s.Put(entry) }
func (b *backend) pathRoleCreate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("name").(string) if name == "" { return logical.ErrorResponse("Missing name"), nil } roleDB := data.Get("db").(string) if roleDB == "" { return logical.ErrorResponse("db parameter is required"), nil } // Example roles JSON: // // [ "readWrite", { "role": "readWrite", "db": "test" } ] // // For storage, we convert such an array into a homogeneous array of role documents like: // // [ { "role": "readWrite" }, { "role": "readWrite", "db": "test" } ] // var roles []mongodbRole rolesJson := []byte(data.Get("roles").(string)) if len(rolesJson) > 0 { var rolesArray []interface{} err := json.Unmarshal(rolesJson, &rolesArray) if err != nil { return nil, err } for _, rawRole := range rolesArray { switch role := rawRole.(type) { case string: roles = append(roles, mongodbRole{Role: role}) case map[string]interface{}: if db, ok := role["db"].(string); ok { if roleName, ok := role["role"].(string); ok { roles = append(roles, mongodbRole{Role: roleName, DB: db}) } } } } } // Store it entry, err := logical.StorageEntryJSON("role/"+name, &roleStorageEntry{ DB: roleDB, MongoDBRoles: roles, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathConfigWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { cfg := &ConfigEntry{} url := d.Get("url").(string) if url != "" { cfg.Url = strings.ToLower(url) } userattr := d.Get("userattr").(string) if userattr != "" { cfg.UserAttr = strings.ToLower(userattr) } userdn := d.Get("userdn").(string) if userdn != "" { cfg.UserDN = userdn } groupdn := d.Get("groupdn").(string) if groupdn != "" { cfg.GroupDN = groupdn } upndomain := d.Get("upndomain").(string) if groupdn != "" { cfg.UPNDomain = upndomain } certificate := d.Get("certificate").(string) if certificate != "" { cfg.Certificate = certificate } insecureTLS := d.Get("insecure_tls").(bool) if insecureTLS { cfg.InsecureTLS = insecureTLS } startTLS := d.Get("starttls").(bool) if startTLS { cfg.StartTLS = startTLS } // Try to connect to the LDAP server, to validate the URL configuration // We can also check the URL at this stage, as anything else would probably // require authentication. conn, cerr := cfg.DialLDAP() if cerr != nil { return logical.ErrorResponse(cerr.Error()), nil } conn.Close() entry, err := logical.StorageEntryJSON("config", cfg) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathConnectionUpdate(req *logical.Request, data *framework.FieldData) (*logical.Response, error) { uri := data.Get("connection_uri").(string) username := data.Get("username").(string) password := data.Get("password").(string) if uri == "" { return logical.ErrorResponse(fmt.Sprintf( "'connection_uri' is a required parameter.")), nil } if username == "" { return logical.ErrorResponse(fmt.Sprintf( "'username' is a required parameter.")), nil } if password == "" { return logical.ErrorResponse(fmt.Sprintf( "'password' is a required parameter.")), nil } // Don't check the connection_url if verification is disabled verifyConnection := data.Get("verify_connection").(bool) if verifyConnection { // Create RabbitMQ management client client, err := rabbithole.NewClient(uri, username, password) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error info: %s", err)), nil } // Verify provided user is able to list users _, err = client.ListUsers() if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error validating connection info by listing users: %s", err)), nil } } // Store it entry, err := logical.StorageEntryJSON("config/connection", connectionConfig{ URI: uri, Username: username, Password: password, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } // Reset the client connection b.ResetClient() return nil, nil }
func (b *backend) pathConnectionWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { connValue := data.Get("value").(string) connURL := data.Get("connection_url").(string) if connURL == "" { if connValue == "" { return logical.ErrorResponse("the connection_url parameter must be supplied"), nil } else { connURL = connValue } } maxOpenConns := data.Get("max_open_connections").(int) if maxOpenConns == 0 { maxOpenConns = 2 } // Don't check the connection_url if verification is disabled verifyConnection := data.Get("verify_connection").(bool) if verifyConnection { // Verify the string db, err := sql.Open("mysql", connURL) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "error validating connection info: %s", err)), nil } defer db.Close() if err := db.Ping(); err != nil { return logical.ErrorResponse(fmt.Sprintf( "error validating connection info: %s", err)), nil } } // Store it entry, err := logical.StorageEntryJSON("config/connection", connectionConfig{ ConnectionURL: connURL, MaxOpenConnections: maxOpenConns, VerifyConnection: verifyConnection, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } // Reset the DB connection b.ResetDB() resp := &logical.Response{} resp.AddWarning("Read access to this endpoint should be controlled via ACLs as it will return the connection URL as it is, including passwords, if any.") return resp, nil }
// Stores an instance ID and the information required to validate further login/renewal attempts from // the same instance ID. func setWhitelistIdentityEntry(s logical.Storage, instanceID string, identity *whitelistIdentity) error { entry, err := logical.StorageEntryJSON("whitelist/identity/"+instanceID, identity) if err != nil { return err } if err := s.Put(entry); err != nil { return err } return nil }
func (b *backend) pathCAWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { pemBundle := data.Get("pem_bundle").(string) parsedBundle, err := certutil.ParsePEMBundle(pemBundle) if err != nil { switch err.(type) { case errutil.InternalError: return nil, err default: return logical.ErrorResponse(err.Error()), nil } } if parsedBundle.PrivateKey == nil || parsedBundle.PrivateKeyType == certutil.UnknownPrivateKey { return logical.ErrorResponse("private key not found in the PEM bundle"), nil } if parsedBundle.Certificate == nil { return logical.ErrorResponse("no certificate found in the PEM bundle"), nil } if !parsedBundle.Certificate.IsCA { return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil } cb, err := parsedBundle.ToCertBundle() if err != nil { return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err) } entry, err := logical.StorageEntryJSON("config/ca_bundle", cb) if err != nil { return nil, err } err = req.Storage.Put(entry) if err != nil { return nil, err } // For ease of later use, also store just the certificate at a known // location, plus a fresh CRL entry.Key = "ca" entry.Value = parsedBundle.CertificateBytes err = req.Storage.Put(entry) if err != nil { return nil, err } err = buildCRL(b, req) return nil, err }
func (b *backend) pathCertWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { name := strings.ToLower(d.Get("name").(string)) certificate := d.Get("certificate").(string) displayName := d.Get("display_name").(string) policies := strings.Split(d.Get("policies").(string), ",") for i, p := range policies { policies[i] = strings.TrimSpace(p) } // Default the display name to the certificate name if not given if displayName == "" { displayName = name } if len(policies) == 0 { return logical.ErrorResponse("policies required"), nil } parsed := parsePEM([]byte(certificate)) if len(parsed) == 0 { return logical.ErrorResponse("failed to parse certificate"), nil } certEntry := &CertEntry{ Name: name, Certificate: certificate, DisplayName: displayName, Policies: policies, } // Parse the lease duration or default to backend/system default var err error maxTTL := b.System().MaxLeaseTTL() ttl := time.Duration(d.Get("ttl").(int)) * time.Second if ttl == time.Duration(0) { ttl = time.Second * time.Duration(d.Get("lease").(int)) } if ttl > maxTTL { return logical.ErrorResponse(fmt.Sprintf("Given TTL of %d seconds greater than current mount/system default of %d seconds", ttl/time.Second, maxTTL/time.Second)), nil } if ttl > time.Duration(0) { certEntry.TTL = ttl } // Store it entry, err := logical.StorageEntryJSON("cert/"+name, certEntry) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
// Stores the given list of roles at zeroaddress endpoint func (b *backend) putZeroAddressRoles(s logical.Storage, roles []string) error { entry, err := logical.StorageEntryJSON("config/zeroaddress", &zeroAddressRoles{ Roles: roles, }) if err != nil { return err } if err := s.Put(entry); err != nil { return err } return nil }
func pathRolesWrite( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { tokenType := d.Get("token_type").(string) switch tokenType { case "client": case "management": default: return logical.ErrorResponse( "token_type must be \"client\" or \"management\""), nil } name := d.Get("name").(string) policy := d.Get("policy").(string) var policyRaw []byte var err error if tokenType != "management" { if policy == "" { return logical.ErrorResponse( "policy cannot be empty when not using management tokens"), nil } policyRaw, err = base64.StdEncoding.DecodeString(d.Get("policy").(string)) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "Error decoding policy base64: %s", err)), nil } } var lease time.Duration leaseParam := d.Get("lease").(string) if leaseParam != "" { lease, err = time.ParseDuration(leaseParam) if err != nil { return logical.ErrorResponse(fmt.Sprintf( "error parsing given lease of %s: %s", leaseParam, err)), nil } } entry, err := logical.StorageEntryJSON("policy/"+name, roleConfig{ Policy: string(policyRaw), Lease: lease, TokenType: tokenType, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }
func (b *backend) pathConfigWrite( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { organization := data.Get("organization").(string) baseURL := data.Get("base_url").(string) if len(baseURL) != 0 { _, err := url.Parse(baseURL) if err != nil { return logical.ErrorResponse(fmt.Sprintf("Error parsing given base_url: %s", err)), nil } } var ttl time.Duration var err error ttlRaw, ok := data.GetOk("ttl") if !ok || len(ttlRaw.(string)) == 0 { ttl = 0 } else { ttl, err = time.ParseDuration(ttlRaw.(string)) if err != nil { return logical.ErrorResponse(fmt.Sprintf("Invalid 'ttl':%s", err)), nil } } var maxTTL time.Duration maxTTLRaw, ok := data.GetOk("max_ttl") if !ok || len(maxTTLRaw.(string)) == 0 { maxTTL = 0 } else { maxTTL, err = time.ParseDuration(maxTTLRaw.(string)) if err != nil { return logical.ErrorResponse(fmt.Sprintf("Invalid 'max_ttl':%s", err)), nil } } entry, err := logical.StorageEntryJSON("config", config{ Org: organization, BaseURL: baseURL, TTL: ttl, MaxTTL: maxTTL, }) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } return nil, nil }