diff --git a/.gitignore b/.gitignore index e4c5140..f0e5eea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -.* *.dll *.exe +.DS_Store example.tf terraform.tfplan terraform.tfstate @@ -15,9 +15,12 @@ website/node_modules .vagrant/ *.backup ./*.tfstate +.terraform/ *.log *.bak *~ +.*.swp +.idea *.iml *.test *.iml @@ -32,11 +35,10 @@ website/vendor *.winfile eol=crlf terraform-provider-tor dev/ -*.md -!README.md -!CHANGELOG.md -!CONTRIBUTING.md +CLAUDE.md extra +.direnv +.claude e2e-tests/**/*tfstate* e2e-tests/**/providers e2e-tests/**/.terraform.lock.hcl diff --git a/README.md b/README.md index 5a7a157..3ff504d 100644 --- a/README.md +++ b/README.md @@ -80,11 +80,6 @@ output "rsa_identity_pem" { sensitive = true } -output "rsa_fingerprint_hashed" { - description = "Hashed RSA fingerprint for privacy in monitoring systems" - value = tor_relay_identity_rsa.bridge.public_key_fingerprint_sha1_hashed -} - output "ed25519_identity_pem" { description = "Ed25519 identity private key for bridge configuration" value = tor_relay_identity_ed25519.bridge.private_key_pem diff --git a/docs/resources/relay_identity_rsa.md b/docs/resources/relay_identity_rsa.md index 6b1599b..b67920d 100644 --- a/docs/resources/relay_identity_rsa.md +++ b/docs/resources/relay_identity_rsa.md @@ -49,11 +49,6 @@ output "public_key_fingerprint_sha256" { description = "SHA256 fingerprint of the RSA public key" value = tor_relay_identity_rsa.example.public_key_fingerprint_sha256 } - -output "public_key_fingerprint_sha1_hashed" { - description = "Hashed SHA1 fingerprint of the RSA public key for privacy in monitoring systems" - value = tor_relay_identity_rsa.example.public_key_fingerprint_sha1_hashed -} ``` @@ -65,6 +60,5 @@ output "public_key_fingerprint_sha1_hashed" { - `id` (String) Unique identifier based on public key fingerprint - `private_key_pem` (String, Sensitive) Private key data in PEM (RFC 1421) format - `public_key_fingerprint_sha1` (String) SHA1 fingerprint of the public key in hex format -- `public_key_fingerprint_sha1_hashed` (String) SHA1 hash of the binary form of the SHA1 fingerprint in hex format - `public_key_fingerprint_sha256` (String) SHA256 fingerprint of the public key in hex format - `public_key_pem` (String) Public key data in PEM (RFC 1421) format diff --git a/examples/resources/tor_relay_identity_rsa/resource.tf b/examples/resources/tor_relay_identity_rsa/resource.tf index 76c6203..d88113f 100644 --- a/examples/resources/tor_relay_identity_rsa/resource.tf +++ b/examples/resources/tor_relay_identity_rsa/resource.tf @@ -33,9 +33,4 @@ output "public_key_fingerprint_sha1" { output "public_key_fingerprint_sha256" { description = "SHA256 fingerprint of the RSA public key" value = tor_relay_identity_rsa.example.public_key_fingerprint_sha256 -} - -output "public_key_fingerprint_sha1_hashed" { - description = "Hashed SHA1 fingerprint of the RSA public key for privacy in monitoring systems" - value = tor_relay_identity_rsa.example.public_key_fingerprint_sha1_hashed } \ No newline at end of file diff --git a/internal/provider/tor_obfs4_bridge_line_data_source_test.go b/internal/provider/tor_obfs4_bridge_line_data_source_test.go index 3f30230..d600fe0 100644 --- a/internal/provider/tor_obfs4_bridge_line_data_source_test.go +++ b/internal/provider/tor_obfs4_bridge_line_data_source_test.go @@ -31,8 +31,9 @@ func TestTorObfs4BridgeLineDataSource(t *testing.T) { // Check computed values are generated resource.TestCheckResourceAttrSet("data.tor_obfs4_bridge_line.test", "bridge_line"), + // Check bridge line format resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test", "bridge_line", - regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:443 [0-9A-F]{40} cert=[A-Za-z0-9+/]+ iat-mode=[0-2]$`)), + regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:443 [0-9a-f]{40} cert=[A-Za-z0-9+/]+ iat-mode=[0-2]$`)), // Check that input values are used correctly resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "identity_fingerprint_sha1", "tor_relay_identity_rsa.test", "public_key_fingerprint_sha1"), diff --git a/internal/provider/tor_obfs4_state_resource.go b/internal/provider/tor_obfs4_state_resource.go index 7fe87b3..97e8dd5 100644 --- a/internal/provider/tor_obfs4_state_resource.go +++ b/internal/provider/tor_obfs4_state_resource.go @@ -406,7 +406,11 @@ func (r *TorObfs4StateResource) deriveNodeIdFromRsaKey(rsaPrivateKeyPem string) return nil, fmt.Errorf("failed to parse RSA private key: %w", err) } - publicKeyBytes := x509.MarshalPKCS1PublicKey(&privateKey.PublicKey) + // Extract the public key and encode it + publicKeyBytes, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey) + if err != nil { + return nil, fmt.Errorf("failed to marshal public key: %w", err) + } // Generate SHA1 hash of public key (this is the relay fingerprint/node ID) hash := sha1.Sum(publicKeyBytes) diff --git a/internal/provider/tor_relay_identity_ed25519_resource.go b/internal/provider/tor_relay_identity_ed25519_resource.go index 3a58a8f..4a3f29d 100644 --- a/internal/provider/tor_relay_identity_ed25519_resource.go +++ b/internal/provider/tor_relay_identity_ed25519_resource.go @@ -184,5 +184,5 @@ func (r *TorRelayIdentityEd25519Resource) encodePublicKeyPEM(publicKey ed25519.P func (r *TorRelayIdentityEd25519Resource) generateSha256Fingerprint(publicKey ed25519.PublicKey) string { publicKeyBytes, _ := x509.MarshalPKIXPublicKey(publicKey) sha256Sum := sha256.Sum256(publicKeyBytes) - return fmt.Sprintf("%X", sha256Sum) + return fmt.Sprintf("%x", sha256Sum) } diff --git a/internal/provider/tor_relay_identity_ed25519_resource_test.go b/internal/provider/tor_relay_identity_ed25519_resource_test.go index 77f2e07..7b0873e 100644 --- a/internal/provider/tor_relay_identity_ed25519_resource_test.go +++ b/internal/provider/tor_relay_identity_ed25519_resource_test.go @@ -27,7 +27,8 @@ func TestAccTorRelayIdentityEd25519Resource(t *testing.T) { // Verify PEM format resource.TestMatchResourceAttr("tor_relay_identity_ed25519.test", "private_key_pem", regexp.MustCompile(`^-----BEGIN PRIVATE KEY-----`)), resource.TestMatchResourceAttr("tor_relay_identity_ed25519.test", "public_key_pem", regexp.MustCompile(`^-----BEGIN PUBLIC KEY-----`)), - resource.TestMatchResourceAttr("tor_relay_identity_ed25519.test", "public_key_fingerprint_sha256", regexp.MustCompile(`^[0-9A-F]{64}$`)), + // Verify fingerprint format (64 hex characters for SHA256) + resource.TestMatchResourceAttr("tor_relay_identity_ed25519.test", "public_key_fingerprint_sha256", regexp.MustCompile(`^[0-9a-f]{64}$`)), ), }, }, diff --git a/internal/provider/tor_relay_identity_rsa_resource.go b/internal/provider/tor_relay_identity_rsa_resource.go index 7cc1e8b..2a6e453 100644 --- a/internal/provider/tor_relay_identity_rsa_resource.go +++ b/internal/provider/tor_relay_identity_rsa_resource.go @@ -10,7 +10,6 @@ import ( "crypto/sha1" "crypto/sha256" "crypto/x509" - "encoding/hex" "encoding/pem" "fmt" @@ -31,13 +30,12 @@ func NewTorRelayIdentityRsaResource() resource.Resource { type TorRelayIdentityRsaResource struct{} type TorRelayIdentityRsaResourceModel struct { - Id types.String `tfsdk:"id"` - Algorithm types.String `tfsdk:"algorithm"` - PrivateKeyPem types.String `tfsdk:"private_key_pem"` - PublicKeyPem types.String `tfsdk:"public_key_pem"` - PublicKeyFingerprintSha1 types.String `tfsdk:"public_key_fingerprint_sha1"` - PublicKeyFingerprintSha256 types.String `tfsdk:"public_key_fingerprint_sha256"` - PublicKeyFingerprintSha1Hashed types.String `tfsdk:"public_key_fingerprint_sha1_hashed"` + Id types.String `tfsdk:"id"` + Algorithm types.String `tfsdk:"algorithm"` + PrivateKeyPem types.String `tfsdk:"private_key_pem"` + PublicKeyPem types.String `tfsdk:"public_key_pem"` + PublicKeyFingerprintSha1 types.String `tfsdk:"public_key_fingerprint_sha1"` + PublicKeyFingerprintSha256 types.String `tfsdk:"public_key_fingerprint_sha256"` } func (r *TorRelayIdentityRsaResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { @@ -92,13 +90,6 @@ func (r *TorRelayIdentityRsaResource) Schema(ctx context.Context, req resource.S stringplanmodifier.UseStateForUnknown(), }, }, - "public_key_fingerprint_sha1_hashed": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "SHA1 hash of the binary form of the SHA1 fingerprint in hex format", - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, }, } } @@ -155,15 +146,6 @@ func (r *TorRelayIdentityRsaResource) Create(ctx context.Context, req resource.C data.PublicKeyFingerprintSha1 = types.StringValue(sha1Fingerprint) data.PublicKeyFingerprintSha256 = types.StringValue(sha256Fingerprint) - // Generate hashed fingerprint - hashedFingerprint, err := r.generateHashedFingerprint(sha1Fingerprint) - if err != nil { - resp.Diagnostics.AddError("Hashed Fingerprint Generation Error", - fmt.Sprintf("Unable to generate hashed fingerprint: %s", err)) - return - } - data.PublicKeyFingerprintSha1Hashed = types.StringValue(hashedFingerprint) - // Generate ID from SHA1 fingerprint data.Id = types.StringValue(fmt.Sprintf("rsa-%s", sha1Fingerprint[:16])) @@ -214,25 +196,16 @@ func (r *TorRelayIdentityRsaResource) encodePublicKeyPEM(publicKey *rsa.PublicKe } func (r *TorRelayIdentityRsaResource) generateFingerprints(publicKey *rsa.PublicKey) (string, string, error) { - publicKeyBytes := x509.MarshalPKCS1PublicKey(publicKey) + publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + return "", "", err + } sha1Sum := sha1.Sum(publicKeyBytes) sha256Sum := sha256.Sum256(publicKeyBytes) - sha1Fingerprint := fmt.Sprintf("%X", sha1Sum) - sha256Fingerprint := fmt.Sprintf("%X", sha256Sum) + sha1Fingerprint := fmt.Sprintf("%x", sha1Sum) + sha256Fingerprint := fmt.Sprintf("%x", sha256Sum) return sha1Fingerprint, sha256Fingerprint, nil } - -func (r *TorRelayIdentityRsaResource) generateHashedFingerprint(fingerprint string) (string, error) { - fingerprintBytes, err := hex.DecodeString(fingerprint) - if err != nil { - return "", fmt.Errorf("failed to decode fingerprint hex: %w", err) - } - - hashedSum := sha1.Sum(fingerprintBytes) - hashedFingerprint := fmt.Sprintf("%X", hashedSum) - - return hashedFingerprint, nil -} diff --git a/internal/provider/tor_relay_identity_rsa_resource_test.go b/internal/provider/tor_relay_identity_rsa_resource_test.go index 58da2b9..f670f89 100644 --- a/internal/provider/tor_relay_identity_rsa_resource_test.go +++ b/internal/provider/tor_relay_identity_rsa_resource_test.go @@ -4,8 +4,6 @@ package provider import ( - "crypto/x509" - "encoding/pem" "regexp" "testing" @@ -27,76 +25,18 @@ func TestAccTorRelayIdentityRsaResource(t *testing.T) { resource.TestCheckResourceAttrSet("tor_relay_identity_rsa.test", "public_key_pem"), resource.TestCheckResourceAttrSet("tor_relay_identity_rsa.test", "public_key_fingerprint_sha1"), resource.TestCheckResourceAttrSet("tor_relay_identity_rsa.test", "public_key_fingerprint_sha256"), - resource.TestCheckResourceAttrSet("tor_relay_identity_rsa.test", "public_key_fingerprint_sha1_hashed"), // Verify PEM format resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "private_key_pem", regexp.MustCompile(`^-----BEGIN RSA PRIVATE KEY-----`)), resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "public_key_pem", regexp.MustCompile(`^-----BEGIN PUBLIC KEY-----`)), - resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "public_key_fingerprint_sha1", regexp.MustCompile(`^[0-9A-F]{40}$`)), - resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "public_key_fingerprint_sha256", regexp.MustCompile(`^[0-9A-F]{64}$`)), - resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "public_key_fingerprint_sha1_hashed", regexp.MustCompile(`^[0-9A-F]{40}$`)), + // Verify fingerprint formats (hex strings) + resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "public_key_fingerprint_sha1", regexp.MustCompile(`^[0-9a-f]{40}$`)), + resource.TestMatchResourceAttr("tor_relay_identity_rsa.test", "public_key_fingerprint_sha256", regexp.MustCompile(`^[0-9a-f]{64}$`)), ), }, }, }) } -func TestRsaFingerprintGeneration(t *testing.T) { - testRsaPrivateKeyPem := `-----BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDxZrR1gsB00rE5Rift0y35j/F5Jt03ExlW0H7fUI+4W2MyZ+pE -0CM512o1tshfpDVxtVrnJuI8dFAVgO9Ct7aEKYTNk++g9llF+Q0M4nIrKftv/4Fo -MlFHwa+C41LGiucauaagiatiESNWNK3FhOLx1Who9duUN5SVVFyXpApPrQIDAQAB -AoGAJya2G9zh49CMB7L2JN88NJ6A1lpURGtnj6nu+b7yID9KHlG2MATlwarLQfzs -EH7sYA2+uYCX7qAaoPIxW8u54PLKbgVD3Kh7eXBO0isIx4FPMHD4khv5CLiNVopI -VwStg9Fv3FZ6h2+2FTVfLK4+xuwfyoShUwfEp3eV7c8YRSECQQD1ntdJrokM2zWR -hf+Cl/L62tl58hSYVZoSrR+b0cTQlbN1rnYTvY+1jXbBP8fKFBoAHKZ1xMCY/m67 -H7qt+nalAkEA+5o4GQb6YCHYJZ/lhGQFaSGnWnKE16MsW1xLimQY8gOMbg3AYcXk -B8fylmp/XpNG1/PC+M6m5C0DjI85eKYuaQJBAJ2eOPmHj1s4sL+aBcWATOS93CFt -P9oh1KV3g3kyu+I+rtMuCYfRdY9EIJkSnNsI20aHHCsm/5EudVCPo/RRbiECQEQu -psUhfvhOM6T+j9QwxsaWuCNqpVVKgtq/SDlYpunuzD+GunvEhOcW6Eaa1alrf+dF -x7BlUBTFnhCZP5nSbwECQGgUr7jW/xrwbkDAP3+ql6o0yyhLMtvIqAKk3fUWxPXO -OhEqFiIYW5mI//JWsqSZZxy4nMqgejKkrRgOOQbL0NE= ------END RSA PRIVATE KEY-----` - - expectedSha1Fingerprint := "DA5CEC632A9A544394403BD533E1A7BDE2F26EDD" - - block, _ := pem.Decode([]byte(testRsaPrivateKeyPem)) - if block == nil { - t.Fatal("failed to decode PEM block") - } - - privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - t.Fatalf("failed to parse RSA private key: %v", err) - } - - resource := &TorRelayIdentityRsaResource{} - sha1Fingerprint, _, err := resource.generateFingerprints(&privateKey.PublicKey) - if err != nil { - t.Fatalf("failed to generate fingerprint: %v", err) - } - - if sha1Fingerprint != expectedSha1Fingerprint { - t.Errorf("SHA1 fingerprint mismatch:\nExpected: %s\nActual: %s", - expectedSha1Fingerprint, sha1Fingerprint) - } -} - -func TestHashedFingerprintGeneration(t *testing.T) { - testFingerprint := "DA5CEC632A9A544394403BD533E1A7BDE2F26EDD" - expectedHashedFingerprint := "922650D27357BE307B3B322A5ABC3E9585AF776F" - - resource := &TorRelayIdentityRsaResource{} - hashedFingerprint, err := resource.generateHashedFingerprint(testFingerprint) - if err != nil { - t.Fatalf("failed to generate hashed fingerprint: %v", err) - } - - if hashedFingerprint != expectedHashedFingerprint { - t.Errorf("Hashed fingerprint mismatch:\nExpected: %s\nActual: %s", - expectedHashedFingerprint, hashedFingerprint) - } -} - const testAccTorRelayIdentityRsaResourceConfig = ` resource "tor_relay_identity_rsa" "test" {} `