diff --git a/libs/go/sia/agent/agent.go b/libs/go/sia/agent/agent.go index c6f30703e63..0de9adc8b05 100644 --- a/libs/go/sia/agent/agent.go +++ b/libs/go/sia/agent/agent.go @@ -191,11 +191,11 @@ func RefreshInstance(ztsUrl, metaEndpoint string, opts *options.Options) error { return nil } -func getServiceHostname(opts *options.Options, svc options.Service) string { +func getServiceHostname(opts *options.Options, svc options.Service, fqdn bool) string { if !opts.SanDnsHostname { return "" } - hostname := opts.Provider.GetHostname() + hostname := opts.Provider.GetHostname(fqdn) if hostname == "" { log.Println("No hostname configured for the instance") return "" @@ -210,8 +210,15 @@ func getServiceHostname(opts *options.Options, svc options.Service) string { //suffix is properly configured since we might be having //multiple suffix values if opts.HostnameSuffix == "" { - log.Printf("No hostname suffix configured for the instance: %s\n", hostname) - return "" + // if our initial request was without fqdn then we're + // going to retry with the fqdn otherwise we'll just + // return an empty string + if fqdn { + log.Printf("No hostname suffix configured for the instance: %s\n", hostname) + return "" + } else { + return getServiceHostname(opts, svc, true) + } } hyphenDomain := strings.Replace(opts.Domain, ".", "-", -1) @@ -227,7 +234,7 @@ func registerSvc(svc options.Service, ztsUrl, metaEndpoint string, opts *options //if ssh support is enabled then we need to generate the csr //it is also generated for the primary service only - hostname := getServiceHostname(opts, svc) + hostname := getServiceHostname(opts, svc, false) sshCertRequest, sshCsr, err := generateSshRequest(opts, svc.Name, hostname) if err != nil { return err @@ -326,7 +333,7 @@ func refreshSvc(svc options.Service, ztsUrl, metaEndpoint string, opts *options. //if ssh support is enabled then we need to generate the csr //it is also generated for the primary service only - hostname := getServiceHostname(opts, svc) + hostname := getServiceHostname(opts, svc, false) sshCertRequest, sshCsr, err := generateSshRequest(opts, svc.Name, hostname) if err != nil { return err diff --git a/libs/go/sia/agent/agent_test.go b/libs/go/sia/agent/agent_test.go index 7657bd77b38..45e32b077a2 100644 --- a/libs/go/sia/agent/agent_test.go +++ b/libs/go/sia/agent/agent_test.go @@ -63,15 +63,15 @@ func (tp TestProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (tp TestProvider) GetHostname() string { +func (tp TestProvider) GetHostname(bool) string { return tp.Hostname } -func (tp TestProvider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) { +func (tp TestProvider) AttestationData(string, crypto.PrivateKey, *signature.SignatureInfo) (string, error) { return "", fmt.Errorf("not implemented") } -func (tp TestProvider) PrepareKey(file string) (crypto.PrivateKey, error) { +func (tp TestProvider) PrepareKey(string) (crypto.PrivateKey, error) { return "", fmt.Errorf("not implemented") } @@ -79,23 +79,23 @@ func (tp TestProvider) GetCsrDn() pkix.Name { return pkix.Name{} } -func (tp TestProvider) GetSanDns(service string, includeHost bool, wildcard bool, cnames []string) []string { +func (tp TestProvider) GetSanDns(string, bool, bool, []string) []string { return nil } -func (tp TestProvider) GetSanUri(svc string, opts ip.Opts) []*url.URL { +func (tp TestProvider) GetSanUri(string, ip.Opts) []*url.URL { return nil } -func (tp TestProvider) GetEmail(service string) []string { +func (tp TestProvider) GetEmail(string) []string { return nil } -func (tp TestProvider) GetRoleDnsNames(cert *x509.Certificate, service string) []string { +func (tp TestProvider) GetRoleDnsNames(*x509.Certificate, string) []string { return nil } -func (tp TestProvider) GetSanIp(docIp map[string]bool, ips []net.IP, opts ip.Opts) []net.IP { +func (tp TestProvider) GetSanIp(map[string]bool, []net.IP, ip.Opts) []net.IP { return nil } @@ -103,15 +103,15 @@ func (tp TestProvider) GetSuffix() string { return "" } -func (tp TestProvider) CloudAttestationData(base, svc, ztsServerName string) (string, error) { +func (tp TestProvider) CloudAttestationData(string, string, string) (string, error) { return "abc", nil } -func (tp TestProvider) GetAccountDomainServiceFromMeta(base string) (string, string, string, error) { +func (tp TestProvider) GetAccountDomainServiceFromMeta(string) (string, string, string, error) { return "testAcct", "testDom", "testSvc", nil } -func (tp TestProvider) GetAccessManagementProfileFromMeta(base string) (string, error) { +func (tp TestProvider) GetAccessManagementProfileFromMeta(string) (string, error) { return "testProf", nil } @@ -490,7 +490,7 @@ func TestGetServiceHostname(test *testing.T) { svc := options.Service{ Name: tt.service, } - hostname := getServiceHostname(&opts, svc) + hostname := getServiceHostname(&opts, svc, false) if tt.result != hostname { test.Errorf("%s: invalid value returned - expected: %v, received %v", tt.name, tt.result, hostname) } diff --git a/libs/go/sia/aws/agent/agent.go b/libs/go/sia/aws/agent/agent.go index 053cb323153..41ff51f0fe9 100644 --- a/libs/go/sia/aws/agent/agent.go +++ b/libs/go/sia/aws/agent/agent.go @@ -193,11 +193,11 @@ func RefreshInstance(data []*attestation.AttestationData, ztsUrl string, opts *o return nil } -func getServiceHostname(opts *options.Options, svc options.Service) string { +func getServiceHostname(opts *options.Options, svc options.Service, fqdn bool) string { if !opts.SanDnsHostname { return "" } - hostname := opts.Provider.GetHostname() + hostname := opts.Provider.GetHostname(fqdn) if hostname == "" { log.Println("No hostname configured for the instance") return "" @@ -212,8 +212,15 @@ func getServiceHostname(opts *options.Options, svc options.Service) string { //suffix is properly configured since we might be having //multiple suffix values if opts.HostnameSuffix == "" { - log.Printf("No hostname suffix configured for the instance: %s\n", hostname) - return "" + // if our initial request was without fqdn then we're + // going to retry with the fqdn otherwise we'll just + // return an empty string + if fqdn { + log.Printf("No hostname suffix configured for the instance: %s\n", hostname) + return "" + } else { + return getServiceHostname(opts, svc, true) + } } hyphenDomain := strings.Replace(opts.Domain, ".", "-", -1) @@ -229,7 +236,7 @@ func registerSvc(svc options.Service, data *attestation.AttestationData, ztsUrl //if ssh support is enabled then we need to generate the csr //it is also generated for the primary service only - hostname := getServiceHostname(opts, svc) + hostname := getServiceHostname(opts, svc, false) sshCertRequest, sshCsr, err := generateSshRequest(opts, svc.Name, hostname) if err != nil { return err @@ -329,7 +336,7 @@ func refreshSvc(svc options.Service, data *attestation.AttestationData, ztsUrl s //if ssh support is enabled then we need to generate the csr //it is also generated for the primary service only - hostname := getServiceHostname(opts, svc) + hostname := getServiceHostname(opts, svc, false) sshCertRequest, sshCsr, err := generateSshRequest(opts, svc.Name, hostname) if err != nil { return err diff --git a/libs/go/sia/aws/agent/agent_test.go b/libs/go/sia/aws/agent/agent_test.go index fefa28dd835..8f38550f453 100644 --- a/libs/go/sia/aws/agent/agent_test.go +++ b/libs/go/sia/aws/agent/agent_test.go @@ -65,15 +65,15 @@ func (tp TestProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (tp TestProvider) GetHostname() string { +func (tp TestProvider) GetHostname(bool) string { return tp.Hostname } -func (tp TestProvider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) { +func (tp TestProvider) AttestationData(string, crypto.PrivateKey, *signature.SignatureInfo) (string, error) { return "", fmt.Errorf("not implemented") } -func (tp TestProvider) PrepareKey(file string) (crypto.PrivateKey, error) { +func (tp TestProvider) PrepareKey(string) (crypto.PrivateKey, error) { return "", fmt.Errorf("not implemented") } @@ -81,23 +81,23 @@ func (tp TestProvider) GetCsrDn() pkix.Name { return pkix.Name{} } -func (tp TestProvider) GetSanDns(service string, includeHost bool, wildcard bool, cnames []string) []string { +func (tp TestProvider) GetSanDns(string, bool, bool, []string) []string { return nil } -func (tp TestProvider) GetSanUri(svc string, opts ip.Opts) []*url.URL { +func (tp TestProvider) GetSanUri(string, ip.Opts) []*url.URL { return nil } -func (tp TestProvider) GetEmail(service string) []string { +func (tp TestProvider) GetEmail(string) []string { return nil } -func (tp TestProvider) GetRoleDnsNames(cert *x509.Certificate, service string) []string { +func (tp TestProvider) GetRoleDnsNames(*x509.Certificate, string) []string { return nil } -func (tp TestProvider) GetSanIp(docIp map[string]bool, ips []net.IP, opts ip.Opts) []net.IP { +func (tp TestProvider) GetSanIp(map[string]bool, []net.IP, ip.Opts) []net.IP { return nil } @@ -105,7 +105,7 @@ func (tp TestProvider) GetSuffix() string { return "" } -func (tp TestProvider) CloudAttestationData(base, svc, ztsServerName string) (string, error) { +func (tp TestProvider) CloudAttestationData(string, string, string) (string, error) { a, _ := json.Marshal(&attestation.AttestationData{ Role: "athenz.hockey", }) @@ -113,11 +113,11 @@ func (tp TestProvider) CloudAttestationData(base, svc, ztsServerName string) (st return string(a), nil } -func (tp TestProvider) GetAccountDomainServiceFromMeta(base string) (string, string, string, error) { +func (tp TestProvider) GetAccountDomainServiceFromMeta(string) (string, string, string, error) { return "testAcct", "testDom", "testSvc", nil } -func (tp TestProvider) GetAccessManagementProfileFromMeta(base string) (string, error) { +func (tp TestProvider) GetAccessManagementProfileFromMeta(string) (string, error) { return "testProf", nil } @@ -504,7 +504,7 @@ func TestGetServiceHostname(test *testing.T) { svc := options.Service{ Name: tt.service, } - hostname := getServiceHostname(&opts, svc) + hostname := getServiceHostname(&opts, svc, false) if tt.result != hostname { test.Errorf("%s: invalid value returned - expected: %v, received %v", tt.name, tt.result, hostname) } diff --git a/libs/go/sia/host/provider/provider.go b/libs/go/sia/host/provider/provider.go index 0ac52080871..205451149fb 100644 --- a/libs/go/sia/host/provider/provider.go +++ b/libs/go/sia/host/provider/provider.go @@ -41,7 +41,7 @@ type Provider interface { GetName() string // GetHostname returns the name of the hostname as recognized by the provider - GetHostname() string + GetHostname(bool) string // GetCsrDn returns the x.509 Distinguished Name for use in the CSR GetCsrDn() pkix.Name diff --git a/libs/go/sia/host/utils/utils.go b/libs/go/sia/host/utils/utils.go new file mode 100644 index 00000000000..447014c8896 --- /dev/null +++ b/libs/go/sia/host/utils/utils.go @@ -0,0 +1,46 @@ +// +// Copyright The Athenz Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package utils + +import ( + "log" + "os" + "os/exec" + "strings" +) + +// GetHostname returns the hostname +func GetHostname(fqdn bool) string { + // if the fqdn flag is passed we can't use the go api + // since it doesn't provide an option for it. so we'll + // just resolve calling the hostname directly. + if fqdn { + hostname, err := exec.Command("/bin/hostname", "-f").Output() + if err != nil { + log.Printf("Cannot exec '/bin/hostname -f': %v", err) + return os.Getenv("HOSTNAME") + } + return strings.Trim(string(hostname), "\n\r ") + } else { + hostname, err := os.Hostname() + if err != nil { + log.Printf("Unable to obtain os hostname: %v\n", err) + return os.Getenv("HOSTNAME") + } + return hostname + } +} diff --git a/libs/go/sia/host/utils/utils_test.go b/libs/go/sia/host/utils/utils_test.go new file mode 100644 index 00000000000..89c14585ffa --- /dev/null +++ b/libs/go/sia/host/utils/utils_test.go @@ -0,0 +1,34 @@ +// +// Copyright The Athenz Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package utils + +import ( + "github.com/stretchr/testify/assert" + "os" + "strings" + "testing" +) + +func TestGetHostname(t *testing.T) { + hostname, _ := os.Hostname() + // with false flag we should get the exact same value + assert.Equal(t, hostname, GetHostname(false)) + // with true flag our hostname is the extract string + // or a subset of the response + testHostname := GetHostname(true) + assert.True(t, strings.HasPrefix(testHostname, hostname)) +} diff --git a/libs/go/sia/options/mockawsprovider.go b/libs/go/sia/options/mockawsprovider.go index 2d46f73fdb5..4d0fc9d6aff 100644 --- a/libs/go/sia/options/mockawsprovider.go +++ b/libs/go/sia/options/mockawsprovider.go @@ -24,15 +24,15 @@ func (tp MockAWSProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (tp MockAWSProvider) GetHostname() string { +func (tp MockAWSProvider) GetHostname(bool) string { return tp.Hostname } -func (tp MockAWSProvider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) { +func (tp MockAWSProvider) AttestationData(string, crypto.PrivateKey, *signature.SignatureInfo) (string, error) { return "", fmt.Errorf("not implemented") } -func (tp MockAWSProvider) PrepareKey(file string) (crypto.PrivateKey, error) { +func (tp MockAWSProvider) PrepareKey(string) (crypto.PrivateKey, error) { return "", fmt.Errorf("not implemented") } @@ -40,23 +40,23 @@ func (tp MockAWSProvider) GetCsrDn() pkix.Name { return pkix.Name{} } -func (tp MockAWSProvider) GetSanDns(service string, includeHost bool, wildcard bool, cnames []string) []string { +func (tp MockAWSProvider) GetSanDns(string, bool, bool, []string) []string { return nil } -func (tp MockAWSProvider) GetSanUri(svc string, opts ip.Opts) []*url.URL { +func (tp MockAWSProvider) GetSanUri(string, ip.Opts) []*url.URL { return nil } -func (tp MockAWSProvider) GetEmail(service string) []string { +func (tp MockAWSProvider) GetEmail(string) []string { return nil } -func (tp MockAWSProvider) GetRoleDnsNames(cert *x509.Certificate, service string) []string { +func (tp MockAWSProvider) GetRoleDnsNames(*x509.Certificate, string) []string { return nil } -func (tp MockAWSProvider) GetSanIp(docIp map[string]bool, ips []net.IP, opts ip.Opts) []net.IP { +func (tp MockAWSProvider) GetSanIp(map[string]bool, []net.IP, ip.Opts) []net.IP { return nil } @@ -64,7 +64,7 @@ func (tp MockAWSProvider) GetSuffix() string { return "" } -func (tp MockAWSProvider) CloudAttestationData(base, svc, ztsServerName string) (string, error) { +func (tp MockAWSProvider) CloudAttestationData(string, string, string) (string, error) { a, _ := json.Marshal(&attestation.AttestationData{ Role: "athenz.hockey", }) @@ -72,10 +72,10 @@ func (tp MockAWSProvider) CloudAttestationData(base, svc, ztsServerName string) return string(a), nil } -func (tp MockAWSProvider) GetAccountDomainServiceFromMeta(base string) (string, string, string, error) { +func (tp MockAWSProvider) GetAccountDomainServiceFromMeta(string) (string, string, string, error) { return "mockAWSAccount", "mockAthenzDomain", "mockAthenzService", nil } -func (tp MockAWSProvider) GetAccessManagementProfileFromMeta(base string) (string, error) { +func (tp MockAWSProvider) GetAccessManagementProfileFromMeta(string) (string, error) { return "testProf", nil } diff --git a/provider/aws/sia-ec2/provider.go b/provider/aws/sia-ec2/provider.go index 5bd7429c90f..34d717d5f73 100644 --- a/provider/aws/sia-ec2/provider.go +++ b/provider/aws/sia-ec2/provider.go @@ -23,10 +23,9 @@ import ( "fmt" "github.com/AthenZ/athenz/libs/go/sia/host/ip" "github.com/AthenZ/athenz/libs/go/sia/host/signature" - "log" + "github.com/AthenZ/athenz/libs/go/sia/host/utils" "net" "net/url" - "os" ) type EC2Provider struct { @@ -39,13 +38,8 @@ func (ec2 EC2Provider) GetName() string { } // GetHostname returns the hostname as per the provider -func (ec2 EC2Provider) GetHostname() string { - hostname, err := os.Hostname() - if err != nil { - log.Printf("Unable to obtain os hostname: %v\n", err) - return "" - } - return hostname +func (ec2 EC2Provider) GetHostname(fqdn bool) string { + return utils.GetHostname(fqdn) } func (ec2 EC2Provider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) { diff --git a/provider/aws/sia-eks/provider.go b/provider/aws/sia-eks/provider.go index 65440345785..f49e7484c6d 100644 --- a/provider/aws/sia-eks/provider.go +++ b/provider/aws/sia-eks/provider.go @@ -23,10 +23,9 @@ import ( "fmt" "github.com/AthenZ/athenz/libs/go/sia/host/ip" "github.com/AthenZ/athenz/libs/go/sia/host/signature" - "log" + "github.com/AthenZ/athenz/libs/go/sia/host/utils" "net" "net/url" - "os" ) type EKSProvider struct { @@ -39,13 +38,8 @@ func (eks EKSProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (eks EKSProvider) GetHostname() string { - hostname, err := os.Hostname() - if err != nil { - log.Printf("Unable to obtain os hostname: %v\n", err) - return os.Getenv("HOSTNAME") - } - return hostname +func (eks EKSProvider) GetHostname(fqdn bool) string { + return utils.GetHostname(fqdn) } func (eks EKSProvider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) { diff --git a/provider/aws/sia-fargate/provider.go b/provider/aws/sia-fargate/provider.go index 72bf628f844..5191291ea68 100644 --- a/provider/aws/sia-fargate/provider.go +++ b/provider/aws/sia-fargate/provider.go @@ -37,7 +37,7 @@ func (fargate FargateProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (fargate FargateProvider) GetHostname() string { +func (fargate FargateProvider) GetHostname(fqdn bool) string { return "" } diff --git a/provider/gcp/sia-gce/provider.go b/provider/gcp/sia-gce/provider.go index fdab967774c..4a82a66365d 100644 --- a/provider/gcp/sia-gce/provider.go +++ b/provider/gcp/sia-gce/provider.go @@ -25,10 +25,9 @@ import ( "github.com/AthenZ/athenz/libs/go/sia/gcp/meta" "github.com/AthenZ/athenz/libs/go/sia/host/ip" "github.com/AthenZ/athenz/libs/go/sia/host/signature" - "log" + "github.com/AthenZ/athenz/libs/go/sia/host/utils" "net" "net/url" - "os" ) type GCEProvider struct { @@ -41,13 +40,8 @@ func (gke GCEProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (gke GCEProvider) GetHostname() string { - hostname, err := os.Hostname() - if err != nil { - log.Printf("Unable to obtain os hostname: %v\n", err) - return os.Getenv("HOSTNAME") - } - return hostname +func (gke GCEProvider) GetHostname(fqdn bool) string { + return utils.GetHostname(fqdn) } func (gke GCEProvider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) { diff --git a/provider/gcp/sia-gke/provider.go b/provider/gcp/sia-gke/provider.go index e807e4a92e1..3e5509d93a9 100644 --- a/provider/gcp/sia-gke/provider.go +++ b/provider/gcp/sia-gke/provider.go @@ -25,10 +25,9 @@ import ( "github.com/AthenZ/athenz/libs/go/sia/gcp/meta" "github.com/AthenZ/athenz/libs/go/sia/host/ip" "github.com/AthenZ/athenz/libs/go/sia/host/signature" - "log" + "github.com/AthenZ/athenz/libs/go/sia/host/utils" "net" "net/url" - "os" ) type GKEProvider struct { @@ -41,13 +40,8 @@ func (gke GKEProvider) GetName() string { } // GetHostname returns the hostname as per the provider -func (gke GKEProvider) GetHostname() string { - hostname, err := os.Hostname() - if err != nil { - log.Printf("Unable to obtain os hostname: %v\n", err) - return os.Getenv("HOSTNAME") - } - return hostname +func (gke GKEProvider) GetHostname(fqdn bool) string { + return utils.GetHostname(fqdn) } func (gke GKEProvider) AttestationData(svc string, key crypto.PrivateKey, sigInfo *signature.SignatureInfo) (string, error) {