this is my quickfix branch and i will use to do my quickfixes

This commit is contained in:
2025-05-14 15:00:45 -04:00
parent bcd0c19ead
commit 0ff36d6890
7 changed files with 98 additions and 255 deletions

View File

@@ -55,21 +55,9 @@ var (
// algorithm isn't supported.
ErrUnsupportedHash = errors.New("unsupported hash algorithm")
// Predefined system store names.
// See: https://learn.microsoft.com/en-us/windows/win32/seccrypto/system-store-locations
SystemStoreNames = []string{
"MY",
"Root",
"Trust",
"CA",
}
// Signing name for the IAM Roles Anywhere service
ROLESANYWHERE_SIGNING_NAME = "rolesanywhere"
RolesanywhereSigningName = "rolesanywhere"
)
// Interface that all signers will have to implement
// (as a result, they will also implement crypto.Signer)
type Signer interface {
Public() crypto.PublicKey
Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error)
@@ -78,7 +66,6 @@ type Signer interface {
Close()
}
// Container for certificate data returned to the SDK as JSON.
type CertificateData struct {
// Type for the key contained in the certificate.
// Passed back to the `sign-string` command
@@ -93,7 +80,6 @@ type CertificateData struct {
Algorithms []string `json:"supportedAlgorithms"`
}
// Container that adheres to the format of credential_process output as specified by AWS.
type CredentialProcessOutput struct {
// This field should be hard-coded to 1 for now.
Version int `json:"Version"`
@@ -118,17 +104,15 @@ type CertificateContainer struct {
// Define constants used in signing
const (
aws4_x509_rsa_sha256 = "AWS4-X509-RSA-SHA256"
aws4_x509_ecdsa_sha256 = "AWS4-X509-ECDSA-SHA256"
timeFormat = "20060102T150405Z"
shortTimeFormat = "20060102"
x_amz_date = "X-Amz-Date"
x_amz_x509 = "X-Amz-X509"
x_amz_x509_chain = "X-Amz-X509-Chain"
x_amz_content_sha256 = "X-Amz-Content-Sha256"
authorization = "Authorization"
host = "Host"
emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`
aws4X509RsaSha256 = "AWS4-X509-RSA-SHA256"
aws4X509EcdsaSha256 = "AWS4-X509-ECDSA-SHA256"
timeFormat = "20060102T150405Z"
shortTimeFormat = "20060102"
xAmzDate = "X-Amz-Date"
xAmzX509 = "X-Amz-X509"
xAmzX509Chain = "X-Amz-X509-Chain"
authorization = "Authorization"
host = "Host"
)
// Headers that aren't included in calculating the signature
@@ -138,11 +122,10 @@ var ignoredHeaderKeys = map[string]bool{
"X-Amzn-Trace-Id": true,
}
var Debug bool = false
var Debug = false
// Prompts the user for their password
func GetPassword(ttyReadFile *os.File, ttyWriteFile *os.File, prompt string, parseErrMsg string) (string, error) {
fmt.Fprintln(ttyWriteFile, prompt)
_, _ = fmt.Fprintln(ttyWriteFile, prompt)
passwordBytes, err := term.ReadPassword(int(ttyReadFile.Fd()))
if err != nil {
return "", errors.New(parseErrMsg)
@@ -220,13 +203,17 @@ func PasswordPrompt(passwordPromptInput PasswordPromptProps) (string, interface{
if err != nil {
return "", nil, errors.New(parseErrMsg)
}
defer ttyReadFile.Close()
defer func(ttyReadFile *os.File) {
_ = ttyReadFile.Close()
}(ttyReadFile)
ttyWriteFile, err = os.OpenFile(ttyWritePath, os.O_WRONLY, 0)
if err != nil {
return "", nil, errors.New(parseErrMsg)
}
defer ttyWriteFile.Close()
defer func(ttyWriteFile *os.File) {
_ = ttyWriteFile.Close()
}(ttyWriteFile)
// The key has a password, so prompt for it
password, err = GetPassword(ttyReadFile, ttyWriteFile, prompt, parseErrMsg)
@@ -234,7 +221,7 @@ func PasswordPrompt(passwordPromptInput PasswordPromptProps) (string, interface{
return "", nil, err
}
checkPasswordResult, err = checkPassword(password)
for true {
for {
// If we've found the right password, return both it and the result of `checkPassword`
if err == nil {
return password, checkPasswordResult, nil
@@ -250,11 +237,8 @@ func PasswordPrompt(passwordPromptInput PasswordPromptProps) (string, interface{
}
return "", nil, err
}
return "", nil, err
}
// Default function to showcase certificate information
func DefaultCertContainerToString(certContainer CertificateContainer) string {
var certStr string
@@ -272,7 +256,6 @@ func DefaultCertContainerToString(certContainer CertificateContainer) string {
return certStr
}
// CertificateContainerList implements the sort.Interface interface
type CertificateContainerList []CertificateContainer
func (certificateContainerList CertificateContainerList) Less(i, j int) bool {
@@ -312,7 +295,7 @@ func certMatches(certIdentifier CertIdentifier, cert x509.Certificate) bool {
// }
//
// This is defined in RFC3279 §2.2.3 as well as SEC.1.
// I can't find anything which mandates DER but I've seen
// I can't find anything which mandates DER, but I've seen
// OpenSSL refusing to verify it with indeterminate length.
func encodeEcdsaSigValue(signature []byte) (out []byte, err error) {
sigLen := len(signature) / 2
@@ -335,9 +318,6 @@ func GetSigner(opts *CredentialsOpts) (signer Signer, signatureAlgorithm string,
privateKeyId := opts.PrivateKeyId
if privateKeyId == "" {
if opts.CertificateId == "" {
if Debug {
log.Println("attempting to use CertStoreSigner")
}
return GetCertStoreSigner(opts.CertIdentifier, opts.UseLatestExpiringCertificate)
}
privateKeyId = opts.CertificateId
@@ -348,9 +328,7 @@ func GetSigner(opts *CredentialsOpts) (signer Signer, signatureAlgorithm string,
if err == nil {
certificate = cert
} else if opts.PrivateKeyId == "" {
if Debug {
log.Println("not a PEM certificate, so trying PKCS#12")
}
if opts.CertificateBundleId != "" {
return nil, "", errors.New("can't specify certificate chain when" +
" using PKCS#12 files; certificate bundle should be provided" +
@@ -375,17 +353,11 @@ func GetSigner(opts *CredentialsOpts) (signer Signer, signatureAlgorithm string,
}
if strings.HasPrefix(privateKeyId, "pkcs11:") {
if Debug {
log.Println("attempting to use PKCS11Signer")
}
if certificate != nil {
opts.CertificateId = ""
}
return GetPKCS11Signer(opts.LibPkcs11, certificate, certificateChain, opts.PrivateKeyId, opts.CertificateId, opts.ReusePin)
} else if strings.HasPrefix(privateKeyId, "handle:") {
if Debug {
log.Println("attempting to use TPMv2Signer")
}
return GetTPMv2Signer(
GetTPMv2SignerOpts{
certificate,
@@ -399,9 +371,6 @@ func GetSigner(opts *CredentialsOpts) (signer Signer, signatureAlgorithm string,
} else {
tpmKey, err := parseDERFromPEM(privateKeyId, "TSS2 PRIVATE KEY")
if err == nil {
if Debug {
log.Println("attempting to use TPMv2Signer")
}
return GetTPMv2Signer(
GetTPMv2SignerOpts{
certificate,
@@ -424,24 +393,18 @@ func GetSigner(opts *CredentialsOpts) (signer Signer, signatureAlgorithm string,
if certificate == nil {
return nil, "", errors.New("undefined certificate value")
}
if Debug {
log.Println("attempting to use FileSystemSigner")
}
return GetFileSystemSigner(privateKeyId, opts.CertificateId, opts.CertificateBundleId, false, opts.Pkcs8Password)
}
}
// Obtain the date-time, formatted as specified by SigV4
func (signerParams *SignerParams) GetFormattedSigningDateTime() string {
return signerParams.OverriddenDate.UTC().Format(timeFormat)
}
// Obtain the short date-time, formatted as specified by SigV4
func (signerParams *SignerParams) GetFormattedShortSigningDateTime() string {
return signerParams.OverriddenDate.UTC().Format(shortTimeFormat)
}
// Obtain the scope as part of the SigV4-X509 signature
func (signerParams *SignerParams) GetScope() string {
var scopeStringBuilder strings.Builder
scopeStringBuilder.WriteString(signerParams.GetFormattedShortSigningDateTime())
@@ -486,14 +449,14 @@ func CreateRequestSignFinalizeFunction(signer crypto.Signer, signingRegion strin
}
func signRequest(signer crypto.Signer, signingRegion string, signingAlgorithm string, certificate *x509.Certificate, certificateChain []*x509.Certificate, req *http.Request, payloadHash string) {
signerParams := SignerParams{time.Now(), signingRegion, ROLESANYWHERE_SIGNING_NAME, signingAlgorithm}
signerParams := SignerParams{time.Now(), signingRegion, RolesanywhereSigningName, signingAlgorithm}
// Set headers that are necessary for signing
req.Header.Set(host, req.URL.Host)
req.Header.Set(x_amz_date, signerParams.GetFormattedSigningDateTime())
req.Header.Set(x_amz_x509, certificateToString(certificate))
req.Header.Set(xAmzDate, signerParams.GetFormattedSigningDateTime())
req.Header.Set(xAmzX509, certificateToString(certificate))
if certificateChain != nil {
req.Header.Set(x_amz_x509_chain, certificateChainToString(certificateChain))
req.Header.Set(xAmzX509Chain, certificateChainToString(certificateChain))
}
canonicalRequest, signedHeadersString := createCanonicalRequest(req, payloadHash)
@@ -609,7 +572,6 @@ func createCanonicalRequest(r *http.Request, contentSha256 string) (string, stri
return hex.EncodeToString(canonicalRequestStringHashBytes[:]), signedHeadersString
}
// Create the string to sign.
func CreateStringToSign(canonicalRequest string, signerParams SignerParams) string {
var stringToSignStrBuilder strings.Builder
stringToSignStrBuilder.WriteString(signerParams.SigningAlgorithm)
@@ -623,8 +585,7 @@ func CreateStringToSign(canonicalRequest string, signerParams SignerParams) stri
return stringToSign
}
// Builds the complete authorization header
func BuildAuthorizationHeader(request *http.Request, signedHeadersString string, signature string, certificate *x509.Certificate, signerParams SignerParams) string {
func BuildAuthorizationHeader(_ *http.Request, signedHeadersString string, signature string, certificate *x509.Certificate, signerParams SignerParams) string {
signingCredentials := certificate.SerialNumber.String() + "/" + signerParams.GetScope()
credential := "Credential=" + signingCredentials
signerHeaders := "SignedHeaders=" + signedHeadersString
@@ -645,20 +606,20 @@ func BuildAuthorizationHeader(request *http.Request, signedHeadersString string,
func encodeDer(der []byte) (string, error) {
var buf bytes.Buffer
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
encoder.Write(der)
encoder.Close()
_, _ = encoder.Write(der)
_ = encoder.Close()
return buf.String(), nil
}
func parseDERFromPEM(pemDataId string, blockType string) (*pem.Block, error) {
bytes, err := os.ReadFile(pemDataId)
bts, err := os.ReadFile(pemDataId)
if err != nil {
return nil, err
}
var block *pem.Block
for len(bytes) > 0 {
block, bytes = pem.Decode(bytes)
for len(bts) > 0 {
block, bts = pem.Decode(bts)
if block == nil {
return nil, errors.New("unable to parse PEM data")
}
@@ -669,17 +630,16 @@ func parseDERFromPEM(pemDataId string, blockType string) (*pem.Block, error) {
return nil, errors.New("requested block type could not be found")
}
// Reads certificate bundle data from a file, whose path is provided
func ReadCertificateBundleData(certificateBundleId string) ([]*x509.Certificate, error) {
bytes, err := os.ReadFile(certificateBundleId)
bts, err := os.ReadFile(certificateBundleId)
if err != nil {
return nil, err
}
var derBytes []byte
var block *pem.Block
for len(bytes) > 0 {
block, bytes = pem.Decode(bytes)
for len(bts) > 0 {
block, bts = pem.Decode(bts)
if block == nil {
break
}
@@ -721,30 +681,21 @@ func readRSAPrivateKey(privateKeyId string) (*rsa.PrivateKey, error) {
return privateKey, nil
}
// Reads and parses a PKCS#12 file (which should contain an end-entity
// certificate (optional), certificate chain (optional), and the key
// associated with the end-entity certificate). The end-entity certificate
// will be the first certificate in the returned chain. This method assumes
// that there is exactly one certificate that doesn't issue any others within
// the container and treats that as the end-entity certificate. Also, the
// order of the other certificates in the chain aren't guaranteed. It's
// also not guaranteed that those certificates form a chain with the
// end-entity certificate either.
func ReadPKCS12Data(certificateId string) (certChain []*x509.Certificate, privateKey crypto.PrivateKey, err error) {
var (
bytes []byte
bts []byte
pemBlocks []*pem.Block
parsedCerts []*x509.Certificate
certMap map[string]*x509.Certificate
endEntityFoundIndex int
)
bytes, err = os.ReadFile(certificateId)
bts, err = os.ReadFile(certificateId)
if err != nil {
return nil, nil, err
}
pemBlocks, err = pkcs12.ToPEM(bytes, "")
pemBlocks, err = pkcs12.ToPEM(bts, "")
if err != nil {
return nil, "", err
}
@@ -760,11 +711,6 @@ func ReadPKCS12Data(certificateId string) (certChain []*x509.Certificate, privat
privateKey = privateKeyTmp
continue
}
// If neither a certificate nor a private key could be parsed from the
// Block, ignore it and continue.
if Debug {
log.Println("unable to parse PEM block in PKCS#12 file - skipping")
}
}
certMap = make(map[string]*x509.Certificate)
@@ -784,10 +730,6 @@ func ReadPKCS12Data(certificateId string) (certChain []*x509.Certificate, privat
break
}
}
if Debug {
log.Println("no end-entity certificate found in PKCS#12 file")
}
for i, cert := range parsedCerts {
if i != endEntityFoundIndex {
certChain = append(certChain, cert)
@@ -797,7 +739,6 @@ func ReadPKCS12Data(certificateId string) (certChain []*x509.Certificate, privat
return certChain, privateKey, nil
}
// Load the private key referenced by `privateKeyId`. If `pkcs8Password` is provided, attempt to load an encrypted PKCS#8 key.
func ReadPrivateKeyData(privateKeyId string, pkcs8Password ...string) (crypto.PrivateKey, error) {
if len(pkcs8Password) > 0 && pkcs8Password[0] != "" {
if key, err := readPKCS8EncryptedPrivateKey(privateKeyId, []byte(pkcs8Password[0])); err == nil {
@@ -822,7 +763,6 @@ func ReadPrivateKeyData(privateKeyId string, pkcs8Password ...string) (crypto.Pr
return nil, errors.New("unable to parse private key")
}
// Reads private key data from a *pem.Block.
func ReadPrivateKeyDataFromPEMBlock(block *pem.Block) (key crypto.PrivateKey, err error) {
key, err = x509.ParseECPrivateKey(block.Bytes)
if err == nil {