mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
openstack: move credentials to instance user data
This commit is contained in:
parent
7fb2a357d9
commit
923a41ba01
@ -23,6 +23,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
imdsMetaDataURL = "http://169.254.169.254/openstack/2018-08-27/meta_data.json"
|
imdsMetaDataURL = "http://169.254.169.254/openstack/2018-08-27/meta_data.json"
|
||||||
|
imdsUserDataURL = "http://169.254.169.254/openstack/2018-08-27/user_data"
|
||||||
ec2ImdsBaseURL = "http://169.254.169.254/1.0/meta-data"
|
ec2ImdsBaseURL = "http://169.254.169.254/1.0/meta-data"
|
||||||
maxCacheAge = 12 * time.Hour
|
maxCacheAge = 12 * time.Hour
|
||||||
)
|
)
|
||||||
@ -33,6 +34,7 @@ type imdsClient struct {
|
|||||||
vpcIPCache string
|
vpcIPCache string
|
||||||
vpcIPCacheTime time.Time
|
vpcIPCacheTime time.Time
|
||||||
cache metadataResponse
|
cache metadataResponse
|
||||||
|
userDataCache userDataResponse
|
||||||
cacheTime time.Time
|
cacheTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,73 +131,73 @@ func (c *imdsClient) role(ctx context.Context) (role.Role, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *imdsClient) loadBalancerEndpoint(ctx context.Context) (string, error) {
|
func (c *imdsClient) loadBalancerEndpoint(ctx context.Context) (string, error) {
|
||||||
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.LoadBalancerEndpoint == "" {
|
if c.timeForUpdate(c.cacheTime) || c.userDataCache.LoadBalancerEndpoint == "" {
|
||||||
if err := c.update(ctx); err != nil {
|
if err := c.update(ctx); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cache.Tags.LoadBalancerEndpoint == "" {
|
if c.userDataCache.LoadBalancerEndpoint == "" {
|
||||||
return "", errors.New("unable to get load balancer endpoint")
|
return "", errors.New("unable to get load balancer endpoint")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.cache.Tags.LoadBalancerEndpoint, nil
|
return c.userDataCache.LoadBalancerEndpoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *imdsClient) authURL(ctx context.Context) (string, error) {
|
func (c *imdsClient) authURL(ctx context.Context) (string, error) {
|
||||||
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.AuthURL == "" {
|
if c.timeForUpdate(c.cacheTime) || c.userDataCache.AuthURL == "" {
|
||||||
if err := c.update(ctx); err != nil {
|
if err := c.update(ctx); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cache.Tags.AuthURL == "" {
|
if c.userDataCache.AuthURL == "" {
|
||||||
return "", errors.New("unable to get auth url")
|
return "", errors.New("unable to get auth url")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.cache.Tags.AuthURL, nil
|
return c.userDataCache.AuthURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *imdsClient) userDomainName(ctx context.Context) (string, error) {
|
func (c *imdsClient) userDomainName(ctx context.Context) (string, error) {
|
||||||
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.UserDomainName == "" {
|
if c.timeForUpdate(c.cacheTime) || c.userDataCache.UserDomainName == "" {
|
||||||
if err := c.update(ctx); err != nil {
|
if err := c.update(ctx); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cache.Tags.UserDomainName == "" {
|
if c.userDataCache.UserDomainName == "" {
|
||||||
return "", errors.New("unable to get user domain name")
|
return "", errors.New("unable to get user domain name")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.cache.Tags.UserDomainName, nil
|
return c.userDataCache.UserDomainName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *imdsClient) username(ctx context.Context) (string, error) {
|
func (c *imdsClient) username(ctx context.Context) (string, error) {
|
||||||
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.Username == "" {
|
if c.timeForUpdate(c.cacheTime) || c.userDataCache.Username == "" {
|
||||||
if err := c.update(ctx); err != nil {
|
if err := c.update(ctx); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cache.Tags.Username == "" {
|
if c.userDataCache.Username == "" {
|
||||||
return "", errors.New("unable to get token name")
|
return "", errors.New("unable to get token name")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.cache.Tags.Username, nil
|
return c.userDataCache.Username, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *imdsClient) password(ctx context.Context) (string, error) {
|
func (c *imdsClient) password(ctx context.Context) (string, error) {
|
||||||
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.Password == "" {
|
if c.timeForUpdate(c.cacheTime) || c.userDataCache.Password == "" {
|
||||||
if err := c.update(ctx); err != nil {
|
if err := c.update(ctx); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cache.Tags.Password == "" {
|
if c.userDataCache.Password == "" {
|
||||||
return "", errors.New("unable to get token password")
|
return "", errors.New("unable to get token password")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.cache.Tags.Password, nil
|
return c.userDataCache.Password, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeForUpdate checks whether an update is needed due to cache age.
|
// timeForUpdate checks whether an update is needed due to cache age.
|
||||||
@ -203,18 +205,41 @@ func (c *imdsClient) timeForUpdate(t time.Time) bool {
|
|||||||
return time.Since(t) > maxCacheAge
|
return time.Since(t) > maxCacheAge
|
||||||
}
|
}
|
||||||
|
|
||||||
// update updates instance metadata from the azure imds API.
|
|
||||||
func (c *imdsClient) update(ctx context.Context) error {
|
func (c *imdsClient) update(ctx context.Context) error {
|
||||||
|
if err := c.updateInstanceMetadata(ctx); err != nil {
|
||||||
|
return fmt.Errorf("updating instance metadata: %w", err)
|
||||||
|
}
|
||||||
|
if err := c.updateUserData(ctx); err != nil {
|
||||||
|
return fmt.Errorf("updating user data: %w", err)
|
||||||
|
}
|
||||||
|
c.cacheTime = time.Now()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// update updates instance metadata from the azure imds API.
|
||||||
|
func (c *imdsClient) updateInstanceMetadata(ctx context.Context) error {
|
||||||
resp, err := httpGet(ctx, c.client, imdsMetaDataURL)
|
resp, err := httpGet(ctx, c.client, imdsMetaDataURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var metadataResp metadataResponse
|
var metadataResp metadataResponse
|
||||||
if err := json.Unmarshal(resp, &metadataResp); err != nil {
|
if err := json.Unmarshal(resp, &metadataResp); err != nil {
|
||||||
return fmt.Errorf("unmarshalling IMDS metadata response %q: %w", string(resp), err)
|
return fmt.Errorf("unmarshalling IMDS metadata response %q: %w", resp, err)
|
||||||
}
|
}
|
||||||
c.cache = metadataResp
|
c.cache = metadataResp
|
||||||
c.cacheTime = time.Now()
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *imdsClient) updateUserData(ctx context.Context) error {
|
||||||
|
resp, err := httpGet(ctx, c.client, imdsUserDataURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var userdataResp userDataResponse
|
||||||
|
if err := json.Unmarshal(resp, &userdataResp); err != nil {
|
||||||
|
return fmt.Errorf("unmarshalling IMDS user_data response %q: %w", resp, err)
|
||||||
|
}
|
||||||
|
c.userDataCache = userdataResp
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,9 +287,12 @@ type metadataResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type metadataTags struct {
|
type metadataTags struct {
|
||||||
InitSecretHash string `json:"constellation-init-secret-hash,omitempty"`
|
InitSecretHash string `json:"constellation-init-secret-hash,omitempty"`
|
||||||
Role string `json:"constellation-role,omitempty"`
|
Role string `json:"constellation-role,omitempty"`
|
||||||
UID string `json:"constellation-uid,omitempty"`
|
UID string `json:"constellation-uid,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type userDataResponse struct {
|
||||||
AuthURL string `json:"openstack-auth-url,omitempty"`
|
AuthURL string `json:"openstack-auth-url,omitempty"`
|
||||||
UserDomainName string `json:"openstack-user-domain-name,omitempty"`
|
UserDomainName string `json:"openstack-user-domain-name,omitempty"`
|
||||||
Username string `json:"openstack-username,omitempty"`
|
Username string `json:"openstack-username,omitempty"`
|
||||||
|
@ -26,7 +26,7 @@ func TestProviderID(t *testing.T) {
|
|||||||
someErr := errors.New("failed")
|
someErr := errors.New("failed")
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
cache metadataResponse
|
cache any
|
||||||
cacheTime time.Time
|
cacheTime time.Time
|
||||||
newClient httpClientJSONCreateFunc
|
newClient httpClientJSONCreateFunc
|
||||||
wantResult string
|
wantResult string
|
||||||
@ -34,7 +34,7 @@ func TestProviderID(t *testing.T) {
|
|||||||
wantErr bool
|
wantErr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
newTestCases := func(mResp1, mResp2 metadataResponse, expect1, expect2 string) map[string]testCase {
|
newTestCases := func(mResp1, mResp2 any, expect1, expect2 string) map[string]testCase {
|
||||||
return map[string]testCase{
|
return map[string]testCase{
|
||||||
"cached": {
|
"cached": {
|
||||||
cache: mResp1,
|
cache: mResp1,
|
||||||
@ -120,32 +120,32 @@ func TestProviderID(t *testing.T) {
|
|||||||
"authURL": {
|
"authURL": {
|
||||||
method: (*imdsClient).authURL,
|
method: (*imdsClient).authURL,
|
||||||
testCases: newTestCases(
|
testCases: newTestCases(
|
||||||
metadataResponse{Tags: metadataTags{AuthURL: "authURL1"}},
|
userDataResponse{AuthURL: "authURL1"},
|
||||||
metadataResponse{Tags: metadataTags{AuthURL: "authURL2"}},
|
userDataResponse{AuthURL: "authURL2"},
|
||||||
"authURL1", "authURL2",
|
"authURL1", "authURL2",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"userDomainName": {
|
"userDomainName": {
|
||||||
method: (*imdsClient).userDomainName,
|
method: (*imdsClient).userDomainName,
|
||||||
testCases: newTestCases(
|
testCases: newTestCases(
|
||||||
metadataResponse{Tags: metadataTags{UserDomainName: "userDomainName1"}},
|
userDataResponse{UserDomainName: "userDomainName1"},
|
||||||
metadataResponse{Tags: metadataTags{UserDomainName: "userDomainName2"}},
|
userDataResponse{UserDomainName: "userDomainName2"},
|
||||||
"userDomainName1", "userDomainName2",
|
"userDomainName1", "userDomainName2",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"username": {
|
"username": {
|
||||||
method: (*imdsClient).username,
|
method: (*imdsClient).username,
|
||||||
testCases: newTestCases(
|
testCases: newTestCases(
|
||||||
metadataResponse{Tags: metadataTags{Username: "username1"}},
|
userDataResponse{Username: "username1"},
|
||||||
metadataResponse{Tags: metadataTags{Username: "username2"}},
|
userDataResponse{Username: "username2"},
|
||||||
"username1", "username2",
|
"username1", "username2",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
method: (*imdsClient).password,
|
method: (*imdsClient).password,
|
||||||
testCases: newTestCases(
|
testCases: newTestCases(
|
||||||
metadataResponse{Tags: metadataTags{Password: "password1"}},
|
userDataResponse{Password: "password1"},
|
||||||
metadataResponse{Tags: metadataTags{Password: "password2"}},
|
userDataResponse{Password: "password2"},
|
||||||
"password1", "password2",
|
"password1", "password2",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -162,10 +162,18 @@ func TestProviderID(t *testing.T) {
|
|||||||
if tc.newClient != nil {
|
if tc.newClient != nil {
|
||||||
client = tc.newClient(require)
|
client = tc.newClient(require)
|
||||||
}
|
}
|
||||||
|
var cache metadataResponse
|
||||||
|
var userDataCache userDataResponse
|
||||||
|
if _, ok := tc.cache.(metadataResponse); ok {
|
||||||
|
cache = tc.cache.(metadataResponse)
|
||||||
|
} else if _, ok := tc.cache.(userDataResponse); ok {
|
||||||
|
userDataCache = tc.cache.(userDataResponse)
|
||||||
|
}
|
||||||
imds := &imdsClient{
|
imds := &imdsClient{
|
||||||
client: client,
|
client: client,
|
||||||
cache: tc.cache,
|
cache: cache,
|
||||||
cacheTime: tc.cacheTime,
|
userDataCache: userDataCache,
|
||||||
|
cacheTime: tc.cacheTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tu.method(imds, context.Background())
|
result, err := tu.method(imds, context.Background())
|
||||||
@ -373,13 +381,13 @@ type httpClientJSONCreateFunc func(r *require.Assertions) *stubHTTPClientJSON
|
|||||||
|
|
||||||
type stubHTTPClientJSON struct {
|
type stubHTTPClientJSON struct {
|
||||||
require *require.Assertions
|
require *require.Assertions
|
||||||
response metadataResponse
|
response any
|
||||||
code int
|
code int
|
||||||
err error
|
err error
|
||||||
called bool
|
called bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStubHTTPClientJSONFunc(response metadataResponse, statusCode int, err error) httpClientJSONCreateFunc {
|
func newStubHTTPClientJSONFunc(response any, statusCode int, err error) httpClientJSONCreateFunc {
|
||||||
return func(r *require.Assertions) *stubHTTPClientJSON {
|
return func(r *require.Assertions) *stubHTTPClientJSON {
|
||||||
return &stubHTTPClientJSON{
|
return &stubHTTPClientJSON{
|
||||||
response: response,
|
response: response,
|
||||||
|
@ -72,14 +72,16 @@ resource "openstack_compute_instance_v2" "instance_group_member" {
|
|||||||
delete_on_termination = true
|
delete_on_termination = true
|
||||||
}
|
}
|
||||||
metadata = {
|
metadata = {
|
||||||
constellation-role = var.role
|
constellation-role = var.role
|
||||||
constellation-uid = var.uid
|
constellation-uid = var.uid
|
||||||
constellation-init-secret-hash = var.init_secret_hash
|
constellation-init-secret-hash = var.init_secret_hash
|
||||||
|
}
|
||||||
|
user_data = jsonencode({
|
||||||
openstack-auth-url = var.identity_internal_url
|
openstack-auth-url = var.identity_internal_url
|
||||||
openstack-username = var.openstack_username
|
openstack-username = var.openstack_username
|
||||||
openstack-password = var.openstack_password
|
openstack-password = var.openstack_password
|
||||||
openstack-user-domain-name = var.openstack_user_domain_name
|
openstack-user-domain-name = var.openstack_user_domain_name
|
||||||
openstack-load-balancer-endpoint = var.openstack_load_balancer_endpoint
|
openstack-load-balancer-endpoint = var.openstack_load_balancer_endpoint
|
||||||
}
|
})
|
||||||
availability_zone_hints = var.availability_zone
|
availability_zone_hints = length(var.availability_zone) > 0 ? var.availability_zone : null
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user