// nonLockedAWSRole returns the properties set on the given role. This method // does not acquire the read lock before reading the role from the storage. If // locking is desired, use lockedAWSRole instead. func (b *backend) nonLockedAWSRole(s logical.Storage, roleName string) (*awsRoleEntry, error) { if roleName == "" { return nil, fmt.Errorf("missing role name") } entry, err := s.Get("role/" + strings.ToLower(roleName)) if err != nil { return nil, err } if entry == nil { return nil, nil } var result awsRoleEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } // Check if the value held by role ARN field is actually an instance profile ARN if result.BoundIamRoleARN != "" && strings.Contains(result.BoundIamRoleARN, ":instance-profile/") { // If yes, move it to the correct field result.BoundIamInstanceProfileARN = result.BoundIamRoleARN // Reset the old field result.BoundIamRoleARN = "" // Save the update if err = b.nonLockedSetAWSRole(s, roleName, &result); err != nil { return nil, fmt.Errorf("failed to move instance profile ARN to bound_iam_instance_profile_arn field") } } return &result, nil }
func clientIAM(s logical.Storage) (*iam.IAM, error) { entry, err := s.Get("config/root") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf( "root credentials haven't been configured. Please configure\n" + "them at the 'config/root' endpoint") } var config rootConfig if err := entry.DecodeJSON(&config); err != nil { return nil, fmt.Errorf("error reading root configuration: %s", err) } creds := credentials.NewStaticCredentials(config.AccessKey, config.SecretKey, "") awsConfig := &aws.Config{ Credentials: creds, Region: aws.String(config.Region), HTTPClient: cleanhttp.DefaultClient(), } return iam.New(session.New(awsConfig)), nil }
func getRootConfig(s logical.Storage) (*aws.Config, error) { credsConfig := &awsutil.CredentialsConfig{} entry, err := s.Get("config/root") if err != nil { return nil, err } if entry != nil { var config rootConfig if err := entry.DecodeJSON(&config); err != nil { return nil, fmt.Errorf("error reading root configuration: %s", err) } credsConfig.AccessKey = config.AccessKey credsConfig.SecretKey = config.SecretKey credsConfig.Region = config.Region } if credsConfig.Region == "" { credsConfig.Region = "us-east-1" } credsConfig.HTTPClient = cleanhttp.DefaultClient() creds, err := credsConfig.GenerateCredentialChain() if err != nil { return nil, err } return &aws.Config{ Credentials: creds, Region: aws.String(credsConfig.Region), HTTPClient: cleanhttp.DefaultClient(), }, nil }
// DB returns the database connection. func (b *backend) Client(s logical.Storage) (*rabbithole.Client, error) { b.lock.Lock() defer b.lock.Unlock() // If we already have a client, we got it! if b.client != nil { return b.client, nil } // Otherwise, attempt to make connection entry, err := s.Get("config/connection") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf("configure the client connection with config/connection first") } var connConfig connectionConfig if err := entry.DecodeJSON(&connConfig); err != nil { return nil, err } b.client, err = rabbithole.NewClient(connConfig.URI, connConfig.Username, connConfig.Password) if err != nil { return nil, err } return b.client, nil }
// nonLockedAWSPublicCertificateEntry reads the certificate information from // the storage. This method does not acquire lock before reading the storage. // If locking is desired, use lockedAWSPublicCertificateEntry instead. func (b *backend) nonLockedAWSPublicCertificateEntry(s logical.Storage, certName string) (*awsPublicCert, error) { entry, err := s.Get("config/certificate/" + certName) if err != nil { return nil, err } if entry == nil { return nil, nil } var certEntry awsPublicCert if err := entry.DecodeJSON(&certEntry); err != nil { return nil, err } // Handle upgrade for certificate type persistNeeded := false if certEntry.Type == "" { certEntry.Type = "pkcs7" persistNeeded = true } if persistNeeded { if err := b.nonLockedSetAWSPublicCertificateEntry(s, certName, &certEntry); err != nil { return nil, err } } return &certEntry, nil }
func (b *backend) populateCRLs(storage logical.Storage) error { b.crlUpdateMutex.Lock() defer b.crlUpdateMutex.Unlock() keys, err := storage.List("crls/") if err != nil { return fmt.Errorf("error listing CRLs: %v", err) } if keys == nil || len(keys) == 0 { return nil } for _, key := range keys { entry, err := storage.Get("crls/" + key) if err != nil { return fmt.Errorf("error loading CRL %s: %v", key, err) } if entry == nil { continue } var crlInfo CRLInfo err = entry.DecodeJSON(&crlInfo) if err != nil { return fmt.Errorf("error decoding CRL %s: %v", key, err) } b.crls[key] = crlInfo } return nil }
// DB returns the database connection. func (b *backend) DB(s logical.Storage) (*sql.DB, error) { b.logger.Trace("postgres/db: enter") defer b.logger.Trace("postgres/db: exit") b.lock.Lock() defer b.lock.Unlock() // If we already have a DB, we got it! if b.db != nil { if err := b.db.Ping(); err == nil { return b.db, nil } // If the ping was unsuccessful, close it and ignore errors as we'll be // reestablishing anyways b.db.Close() } // Otherwise, attempt to make connection entry, err := s.Get("config/connection") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf("configure the DB connection with config/connection first") } var connConfig connectionConfig if err := entry.DecodeJSON(&connConfig); err != nil { return nil, err } conn := connConfig.ConnectionURL if len(conn) == 0 { conn = connConfig.ConnectionString } // Ensure timezone is set to UTC for all the conenctions if strings.HasPrefix(conn, "postgres://") || strings.HasPrefix(conn, "postgresql://") { if strings.Contains(conn, "?") { conn += "&timezone=utc" } else { conn += "?timezone=utc" } } else { conn += " timezone=utc" } b.db, err = sql.Open("postgres", conn) if err != nil { return nil, err } // Set some connection pool settings. We don't need much of this, // since the request rate shouldn't be high. b.db.SetMaxOpenConns(connConfig.MaxOpenConnections) b.db.SetMaxIdleConns(connConfig.MaxIdleConnections) return b.db, nil }
// DB returns the database connection. func (b *backend) DB(s logical.Storage) (*sql.DB, error) { b.lock.Lock() defer b.lock.Unlock() // If we already have a DB, we got it! if b.db != nil { return b.db, nil } // Otherwise, attempt to make connection entry, err := s.Get("config/connection") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf("configure the DB connection with config/connection first") } var conn string if err := entry.DecodeJSON(&conn); err != nil { return nil, err } b.db, err = sql.Open("postgres", conn) if err != nil { return nil, err } // Set some connection pool settings. We don't need much of this, // since the request rate shouldn't be high. b.db.SetMaxOpenConns(2) return b.db, nil }
// Takes an IP address and role name and checks if the IP is part // of CIDR blocks belonging to the role. func roleContainsIP(s logical.Storage, roleName string, ip string) (bool, error) { if roleName == "" { return false, fmt.Errorf("missing role name") } if ip == "" { return false, fmt.Errorf("missing ip") } roleEntry, err := s.Get(fmt.Sprintf("roles/%s", roleName)) if err != nil { return false, fmt.Errorf("error retrieving role '%s'", err) } if roleEntry == nil { return false, fmt.Errorf("role '%s' not found", roleName) } var role sshRole if err := roleEntry.DecodeJSON(&role); err != nil { return false, fmt.Errorf("error decoding role '%s'", roleName) } if matched, err := cidrListContainsIP(ip, role.CIDRList); err != nil { return false, err } else { return matched, nil } }
// DB returns the database connection. func (b *backend) DB(s logical.Storage) (*gocql.Session, error) { b.lock.Lock() defer b.lock.Unlock() // If we already have a DB, we got it! if b.session != nil { return b.session, nil } entry, err := s.Get("config/connection") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf("Configure the DB connection with config/connection first") } config := &sessionConfig{} if err := entry.DecodeJSON(config); err != nil { return nil, err } return createSession(config, s) }
// NewSalt creates a new salt based on the configuration func NewSalt(view logical.Storage, config *Config) (*Salt, error) { // Setup the configuration if config == nil { config = &Config{} } if config.Location == "" { config.Location = DefaultLocation } if config.HashFunc == nil { config.HashFunc = SHA256Hash } // Create the salt s := &Salt{ config: config, } // Look for the salt raw, err := view.Get(config.Location) if err != nil { return nil, fmt.Errorf("failed to read salt: %v", err) } // Restore the salt if it exists if raw != nil { s.salt = string(raw.Value) } // Generate a new salt if necessary if s.salt == "" { s.salt, err = uuid.GenerateUUID() if err != nil { return nil, fmt.Errorf("failed to generate uuid: %v", err) } s.generated = true if view != nil { raw := &logical.StorageEntry{ Key: config.Location, Value: []byte(s.salt), } if err := view.Put(raw); err != nil { return nil, fmt.Errorf("failed to persist salt: %v", err) } } } if config.HMAC != nil { if len(config.HMACType) == 0 { return nil, fmt.Errorf("HMACType must be defined") } s.hmacType = config.HMACType } return s, nil }
// DB returns the default database connection. func (b *backend) DB(s logical.Storage) (*sql.DB, error) { b.lock.Lock() defer b.lock.Unlock() // If we already have a DB, we got it! if b.db != nil { if err := b.db.Ping(); err == nil { return b.db, nil } // If the ping was unsuccessful, close it and ignore errors as we'll be // reestablishing anyways b.db.Close() } // Otherwise, attempt to make connection entry, err := s.Get("config/connection") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf("configure the DB connection with config/connection first") } var connConfig connectionConfig if err := entry.DecodeJSON(&connConfig); err != nil { return nil, err } connString := connConfig.ConnectionString db, err := sql.Open("mssql", connString) if err != nil { return nil, err } // Set some connection pool settings. We don't need much of this, // since the request rate shouldn't be high. db.SetMaxOpenConns(connConfig.MaxOpenConnections) stmt, err := db.Prepare("SELECT db_name();") if err != nil { return nil, err } defer stmt.Close() err = stmt.QueryRow().Scan(&b.defaultDb) if err != nil { return nil, err } b.db = db return b.db, nil }
// DB returns the database connection. func (b *backend) DB(s logical.Storage) (*sql.DB, error) { b.lock.Lock() defer b.lock.Unlock() // If we already have a DB, we got it! if b.db != nil { return b.db, nil } // Otherwise, attempt to make connection entry, err := s.Get("config/connection") if err != nil { return nil, err } if entry == nil { return nil, fmt.Errorf("configure the DB connection with config/connection first") } var connConfig connectionConfig if err := entry.DecodeJSON(&connConfig); err != nil { return nil, err } conn := connConfig.ConnectionString if len(conn) == 0 { conn = connConfig.ConnectionURL } // Ensure timezone is set to UTC for all the conenctions if strings.HasPrefix(conn, "postgres://") || strings.HasPrefix(conn, "postgresql://") { var err error conn, err = pq.ParseURL(conn) if err != nil { return nil, err } } conn += " timezone=utc" b.db, err = sql.Open("postgres", conn) if err != nil { return nil, err } // Set some connection pool settings. We don't need much of this, // since the request rate shouldn't be high. b.db.SetMaxOpenConns(connConfig.MaxOpenConnections) b.db.SetMaxIdleConns(connConfig.MaxIdleConnections) return b.db, nil }
// Fetch the client configuration required to access the AWS API. func (b *backend) nonLockedClientConfigEntry(s logical.Storage) (*clientConfig, error) { entry, err := s.Get("config/client") if err != nil { return nil, err } if entry == nil { return nil, nil } var result clientConfig if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) Cert(s logical.Storage, n string) (*CertEntry, error) { entry, err := s.Get("cert/" + strings.ToLower(n)) if err != nil { return nil, err } if entry == nil { return nil, nil } var result CertEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
// Fetch an item from the whitelist given an instance ID. func whitelistIdentityEntry(s logical.Storage, instanceID string) (*whitelistIdentity, error) { entry, err := s.Get("whitelist/identity/" + instanceID) if err != nil { return nil, err } if entry == nil { return nil, nil } var result whitelistIdentity if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
// Internal version of the above that does no locking func (b *backend) nonLockedAWSPublicCertificateEntry(s logical.Storage, certName string) (*awsPublicCert, error) { entry, err := s.Get("config/certificate/" + certName) if err != nil { return nil, err } if entry == nil { return nil, nil } var result awsPublicCert if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) nonLockedAWSRole(s logical.Storage, role string) (*awsRoleEntry, error) { entry, err := s.Get("role/" + strings.ToLower(role)) if err != nil { return nil, err } if entry == nil { return nil, nil } var result awsRoleEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) getKey(s logical.Storage, n string) (*sshHostKey, error) { entry, err := s.Get("keys/" + n) if err != nil { return nil, err } if entry == nil { return nil, nil } var result sshHostKey if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) nonLockedBlacklistRoleTagEntry(s logical.Storage, tag string) (*roleTagBlacklistEntry, error) { entry, err := s.Get("blacklist/roletag/" + base64.StdEncoding.EncodeToString([]byte(tag))) if err != nil { return nil, err } if entry == nil { return nil, nil } var result roleTagBlacklistEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) nonLockedConfigTidyIdentities(s logical.Storage) (*tidyWhitelistIdentityConfig, error) { entry, err := s.Get(identityWhitelistConfigPath) if err != nil { return nil, err } if entry == nil { return nil, nil } var result tidyWhitelistIdentityConfig if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
// Config returns the configuration for this backend. func (b *backend) Config(s logical.Storage) (*config, error) { entry, err := s.Get("config") if err != nil { return nil, err } var result config if entry != nil { if err := entry.DecodeJSON(&result); err != nil { return nil, fmt.Errorf("error reading configuration: %s", err) } } return &result, nil }
// Retrieves the list of roles from the zeroaddress endpoint. func (b *backend) getZeroAddressRoles(s logical.Storage) (*zeroAddressRoles, error) { entry, err := s.Get("config/zeroaddress") if err != nil { return nil, err } if entry == nil { return nil, nil } var result zeroAddressRoles if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) User(s logical.Storage, n string) (*UserEntry, error) { entry, err := s.Get("user/" + n) if err != nil { return nil, err } if entry == nil { return nil, nil } var result UserEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
// Lease returns the lease information func (b *backend) Lease(s logical.Storage) (*configLease, error) { entry, err := s.Get("config/lease") if err != nil { return nil, err } if entry == nil { return nil, nil } var result configLease if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) Group(s logical.Storage, n string) (*GroupEntry, error) { entry, err := s.Get("group/" + n) if err != nil { return nil, err } if entry == nil { return nil, nil } var result GroupEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
// Get reads the structure. func (p *PathStruct) Get(s logical.Storage) (map[string]interface{}, error) { entry, err := s.Get(fmt.Sprintf("struct/%s", p.Name)) if err != nil { return nil, err } if entry == nil { return nil, nil } var result map[string]interface{} if err := json.Unmarshal(entry.Value, &result); err != nil { return nil, err } return result, nil }
func (b *backend) nonLockedConfigTidyRoleTags(s logical.Storage) (*tidyBlacklistRoleTagConfig, error) { entry, err := s.Get(roletagBlacklistConfigPath) if err != nil { return nil, err } if entry == nil { return nil, nil } var result tidyBlacklistRoleTagConfig if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) getOTP(s logical.Storage, n string) (*sshOTP, error) { entry, err := s.Get("otp/" + n) if err != nil { return nil, err } if entry == nil { return nil, nil } var result sshOTP if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }
func (b *backend) Role(s logical.Storage, n string) (*roleEntry, error) { entry, err := s.Get("role/" + n) if err != nil { return nil, err } if entry == nil { return nil, nil } var result roleEntry if err := entry.DecodeJSON(&result); err != nil { return nil, err } return &result, nil }