mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
fix: hardcode azure instance identity intermediate certificates (#6402)
This was broken for an airgapped customer!
This commit is contained in:
@ -1,12 +1,10 @@
|
|||||||
package azureidentity
|
package azureidentity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"encoding/pem"
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"go.mozilla.org/pkcs7"
|
"go.mozilla.org/pkcs7"
|
||||||
@ -23,7 +21,7 @@ type metadata struct {
|
|||||||
|
|
||||||
// Validate ensures the signature was signed by an Azure certificate.
|
// Validate ensures the signature was signed by an Azure certificate.
|
||||||
// It returns the associated VM ID if successful.
|
// It returns the associated VM ID if successful.
|
||||||
func Validate(ctx context.Context, signature string, options x509.VerifyOptions) (string, error) {
|
func Validate(signature string, options x509.VerifyOptions) (string, error) {
|
||||||
data, err := base64.StdEncoding.DecodeString(signature)
|
data, err := base64.StdEncoding.DecodeString(signature)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", xerrors.Errorf("decode base64: %w", err)
|
return "", xerrors.Errorf("decode base64: %w", err)
|
||||||
@ -41,24 +39,14 @@ func Validate(ctx context.Context, signature string, options x509.VerifyOptions)
|
|||||||
}
|
}
|
||||||
if options.Intermediates == nil {
|
if options.Intermediates == nil {
|
||||||
options.Intermediates = x509.NewCertPool()
|
options.Intermediates = x509.NewCertPool()
|
||||||
for _, certURL := range signer.IssuingCertificateURL {
|
for _, cert := range certificates {
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", certURL, nil)
|
block, rest := pem.Decode([]byte(cert))
|
||||||
if err != nil {
|
if len(rest) != 0 {
|
||||||
return "", xerrors.Errorf("new request %q: %w", certURL, err)
|
return "", xerrors.Errorf("invalid certificate. %d bytes remain", len(rest))
|
||||||
}
|
}
|
||||||
res, err := http.DefaultClient.Do(req)
|
cert, err := x509.ParseCertificate(block.Bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", xerrors.Errorf("perform request %q: %w", certURL, err)
|
return "", xerrors.Errorf("parse certificate: %w", err)
|
||||||
}
|
|
||||||
data, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
_ = res.Body.Close()
|
|
||||||
return "", xerrors.Errorf("read body %q: %w", certURL, err)
|
|
||||||
}
|
|
||||||
_ = res.Body.Close()
|
|
||||||
cert, err := x509.ParseCertificate(data)
|
|
||||||
if err != nil {
|
|
||||||
return "", xerrors.Errorf("parse certificate %q: %w", certURL, err)
|
|
||||||
}
|
}
|
||||||
options.Intermediates.AddCert(cert)
|
options.Intermediates.AddCert(cert)
|
||||||
}
|
}
|
||||||
@ -76,3 +64,68 @@ func Validate(ctx context.Context, signature string, options x509.VerifyOptions)
|
|||||||
}
|
}
|
||||||
return metadata.VMID, nil
|
return metadata.VMID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var certificates = []string{
|
||||||
|
`-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----`,
|
||||||
|
`-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----`,
|
||||||
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package azureidentity_test
|
package azureidentity_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -19,7 +18,7 @@ func TestValidate(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
ct, err := time.Parse(time.RFC3339, "2023-02-01T00:00:00Z")
|
ct, err := time.Parse(time.RFC3339, "2023-02-01T00:00:00Z")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
vm, err := azureidentity.Validate(context.Background(), signature, x509.VerifyOptions{
|
vm, err := azureidentity.Validate(signature, x509.VerifyOptions{
|
||||||
CurrentTime: ct,
|
CurrentTime: ct,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -37,7 +37,7 @@ func (api *API) postWorkspaceAuthAzureInstanceIdentity(rw http.ResponseWriter, r
|
|||||||
if !httpapi.Read(ctx, rw, r, &req) {
|
if !httpapi.Read(ctx, rw, r, &req) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
instanceID, err := azureidentity.Validate(ctx, req.Signature, api.AzureCertificates)
|
instanceID, err := azureidentity.Validate(req.Signature, api.AzureCertificates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpapi.Write(ctx, rw, http.StatusUnauthorized, codersdk.Response{
|
httpapi.Write(ctx, rw, http.StatusUnauthorized, codersdk.Response{
|
||||||
Message: "Invalid Azure identity.",
|
Message: "Invalid Azure identity.",
|
||||||
|
Reference in New Issue
Block a user