Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_linux_virtual_machine - Normalise SSH keys #9897

Merged
merged 3 commits into from
Dec 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions azurerm/helpers/azure/ssh_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package azure

import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

// NormaliseSSHKey attempts to remove invalid formatting and line breaks that can be present in some cases
// when querying the Azure APIs
func NormaliseSSHKey(input string) (*string, error) {
if input == "" {
return nil, fmt.Errorf("empty string supplied")
}

output := input
output = strings.ReplaceAll(output, "<<~EOT", "")
output = strings.ReplaceAll(output, "EOT", "")
output = strings.ReplaceAll(output, "\r", "")

lines := make([]string, 0)
for _, line := range strings.Split(output, "\n") {
lines = append(lines, strings.TrimSpace(line))
}

normalised := strings.Join(lines, "")

return utils.String(normalised), nil
}
118 changes: 118 additions & 0 deletions azurerm/helpers/azure/ssk_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package azure

import "testing"

func TestNormaliseSSHKey(t *testing.T) {
cases := []struct {
Input string
Error bool
Expected string
}{
{
Input: "",
Error: true,
},
{
// Valid 2048 - no modification needed
Input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0pA4vzGH+cmR+blZnoxO5HorOP1ubD4SxuOiW2DSNTSptlj+mPmFIL6sZeYMvSqAjXK368qL3DKHLpp2+1ws1XnYn/Zx/O4WBQAY7VbtzwFc7w7uirQaK6lVqXn8q4CnO0+5IYHgKLrNMEipwLKo+R3E3e1KrH5Xbyhj5yJzrMe3lWOAPzS27DJvjpN5SGWo65X6qFJRh3q95xOQhSOaEqZ/A2ZtfOuagq3FmASzoo/pbq7ianvnxzAYsb2Hg/9uAvypj4Beli6BP7419aP14XS0yyiW4XTKY/9XZiR/3VIKBN/stGN5NFLw82/j12E1GznbDG9PL7PQhijP7QgJh generated-by-azure",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0pA4vzGH+cmR+blZnoxO5HorOP1ubD4SxuOiW2DSNTSptlj+mPmFIL6sZeYMvSqAjXK368qL3DKHLpp2+1ws1XnYn/Zx/O4WBQAY7VbtzwFc7w7uirQaK6lVqXn8q4CnO0+5IYHgKLrNMEipwLKo+R3E3e1KrH5Xbyhj5yJzrMe3lWOAPzS27DJvjpN5SGWo65X6qFJRh3q95xOQhSOaEqZ/A2ZtfOuagq3FmASzoo/pbq7ianvnxzAYsb2Hg/9uAvypj4Beli6BP7419aP14XS0yyiW4XTKY/9XZiR/3VIKBN/stGN5NFLw82/j12E1GznbDG9PL7PQhijP7QgJh generated-by-azure",
},
{
// Valid 2048 - multiline, as per ARM Template Cache
Input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0pA4vzGH+cmR+blZnoxO5HorOP1ubD4SxuOiW2DSN\r\n" +
"TSptlj+mPmFIL6sZeYMvSqAjXK368qL3DKHLpp2+1ws1XnYn/Zx/O4WBQAY7VbtzwFc7w7uirQaK6lVq\r\n" +
"Xn8q4CnO0+5IYHgKLrNMEipwLKo+R3E3e1KrH5Xbyhj5yJzrMe3lWOAPzS27DJvjpN5SGWo65X6qFJRh\r\n" +
"3q95xOQhSOaEqZ/A2ZtfOuagq3FmASzoo/pbq7ianvnxzAYsb2Hg/9uAvypj4Beli6BP7419aP14XS0y\r\n" +
"yiW4XTKY/9XZiR/3VIKBN/stGN5NFLw82/j12E1GznbDG9PL7PQhijP7QgJh generated-by-azure",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0pA4vzGH+cmR+blZnoxO5HorOP1ubD4SxuOiW2DSNTSptlj+mPmFIL6sZeYMvSqAjXK368qL3DKHLpp2+1ws1XnYn/Zx/O4WBQAY7VbtzwFc7w7uirQaK6lVqXn8q4CnO0+5IYHgKLrNMEipwLKo+R3E3e1KrH5Xbyhj5yJzrMe3lWOAPzS27DJvjpN5SGWo65X6qFJRh3q95xOQhSOaEqZ/A2ZtfOuagq3FmASzoo/pbq7ianvnxzAYsb2Hg/9uAvypj4Beli6BP7419aP14XS0yyiW4XTKY/9XZiR/3VIKBN/stGN5NFLw82/j12E1GznbDG9PL7PQhijP7QgJh generated-by-azure",
},
{
// Valid 2048 - multiline, as per ARM Template Cache Linux newlines
Input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0pA4vzGH+cmR+blZnoxO5HorOP1ubD4SxuOiW2DSN\n" +
"TSptlj+mPmFIL6sZeYMvSqAjXK368qL3DKHLpp2+1ws1XnYn/Zx/O4WBQAY7VbtzwFc7w7uirQaK6lVq\n" +
"Xn8q4CnO0+5IYHgKLrNMEipwLKo+R3E3e1KrH5Xbyhj5yJzrMe3lWOAPzS27DJvjpN5SGWo65X6qFJRh\n" +
"3q95xOQhSOaEqZ/A2ZtfOuagq3FmASzoo/pbq7ianvnxzAYsb2Hg/9uAvypj4Beli6BP7419aP14XS0y\n" +
"yiW4XTKY/9XZiR/3VIKBN/stGN5NFLw82/j12E1GznbDG9PL7PQhijP7QgJh generated-by-azure",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0pA4vzGH+cmR+blZnoxO5HorOP1ubD4SxuOiW2DSNTSptlj+mPmFIL6sZeYMvSqAjXK368qL3DKHLpp2+1ws1XnYn/Zx/O4WBQAY7VbtzwFc7w7uirQaK6lVqXn8q4CnO0+5IYHgKLrNMEipwLKo+R3E3e1KrH5Xbyhj5yJzrMe3lWOAPzS27DJvjpN5SGWo65X6qFJRh3q95xOQhSOaEqZ/A2ZtfOuagq3FmASzoo/pbq7ianvnxzAYsb2Hg/9uAvypj4Beli6BP7419aP14XS0yyiW4XTKY/9XZiR/3VIKBN/stGN5NFLw82/j12E1GznbDG9PL7PQhijP7QgJh generated-by-azure",
},
{
// Valid 4096 - not modification required
Input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wzQn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGKH3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayIoiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpmrJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a3w== generated-by-azure",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wzQn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGKH3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayIoiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpmrJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a3w== generated-by-azure",
},
{
// Valid 4096 - multiline Windows
Input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wz\r\n" +
"Qn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB\r\n" +
"85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGK\r\n" +
"H3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x\r\n" +
"6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayI\r\n" +
"oiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5\r\n" +
"y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpm\r\n" +
"rJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6\r\n" +
"Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a\r\n" +
"3w== generated-by-azure",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wzQn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGKH3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayIoiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpmrJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a3w== generated-by-azure",
},
{
// Valid 4096 - multiline Linux newlines
Input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wz\n" +
"Qn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB\n" +
"85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGK\n" +
"H3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x\n" +
"6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayI\n" +
"oiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5\n" +
"y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpm\n" +
"rJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6\n" +
"Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a\n" +
"3w== generated-by-azure",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wzQn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGKH3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayIoiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpmrJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a3w== generated-by-azure",
},
{
// Valid 4096 - multiline Windows Wrapped
Input: "<<~EOT\r\n" +
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wz\r\n" +
"Qn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB\r\n" +
"85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGK\r\n" +
"H3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x\r\n" +
"6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayI\r\n" +
"oiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5\r\n" +
"y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpm\r\n" +
"rJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6\r\n" +
"Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a\r\n" +
"3w== generated-by-azure" +
"EOT",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wzQn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGKH3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayIoiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpmrJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a3w== generated-by-azure",
},
{
// Valid 4096 - multiline Windows Wrapped with whitespace
Input: "<<~EOT\r\n" +
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wz\r\n " +
"Qn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB\r\n " +
"85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGK\r\n" +
" H3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x\r\n" +
"6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayI\r\n" +
"oiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5\r\n" +
"y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpm\r\n" +
" rJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6\r\n" +
" Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a\r\n " +
"3w== generated-by-azure" +
"EOT",
Expected: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFP6r3wb/79MqRYI4dpgMwmjlrDDrk3A/pehysk1wzQn3lSEUtrNeQsHI6o/8au8Un1ndaZXZl/yWQQDDW4kqGw5ty8xPUZ+DB1ZVWkFOVNAgARl0bMNCgm2kB85l66g0zHWDCKLt+xi8xQiL7tGvdq3SWpogY3pWF2AABXoNDloHEN0mzzjJ09hdAHbygaDDr/9k3uyGKH3x0qo7fx5g8GqTtM3YWRxqUqdtkjsNomq94c/PMybCGR6qRoGI0Cdr/OP6/kszDHwf87B9hpTDMNa6x6FVJSDHc9v0CWePJZpjEOAFN3GCyPFFQTA9jvy026jt43wzyeH0kPe/T0ZZdr9YzQETN1b/oAKWKoayIoiLyJtFqUKcFFJSPcMz9ISgCD5Q/jRxQwMuMHpQ8TslxZ38l+41/0V1LWwKj0IkyJVFVWzu4zhgAZXr5y9Qbsis9sStRc+LU9/FQJ/VzNQfL83l86rH/u3NiPFfqisXILSybtMCD0OoRRHfQvWFsSwgt9JCIqLpmrJXRYs679aHzTHDgitlovJyprwqrbjg5N3XNSB5FohAUJUnVMF8z+qzvb4pPhly6mj6tiSJGYbXPngN6Iv8t3mRko3PbYLrWuxMb345BxcD+j9XteUgm1j/10qrSvqq+1R+/FAFPYwLXCflZgKst2g8/rEiVQz+a3w== generated-by-azure",
},
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
}

for _, tc := range cases {
t.Run(tc.Input, func(t *testing.T) {
output, err := NormaliseSSHKey(tc.Input)
if err != nil {
if !tc.Error {
t.Fatalf("expected NormaliseSSHKey to error")
}
}
if output != nil && *output != tc.Expected {
t.Fatalf("Expected %q, got %q", tc.Expected, *output)
}
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ func resourceLinuxVirtualMachineRead(d *schema.ResourceData, meta interface{}) e
if err != nil {
return fmt.Errorf("flattening `admin_ssh_key`: %+v", err)
}
if err := d.Set("admin_ssh_key", flattenedSSHKeys); err != nil {
if err := d.Set("admin_ssh_key", schema.NewSet(SSHKeySchemaHash, *flattenedSSHKeys)); err != nil {
return fmt.Errorf("setting `admin_ssh_key`: %+v", err)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ func resourceArmLinuxVirtualMachineScaleSetRead(d *schema.ResourceData, meta int
if err != nil {
return fmt.Errorf("Error flattening `admin_ssh_key`: %+v", err)
}
if err := d.Set("admin_ssh_key", flattenedSshKeys); err != nil {
if err := d.Set("admin_ssh_key", schema.NewSet(SSHKeySchemaHash, *flattenedSshKeys)); err != nil {
return fmt.Errorf("Error setting `admin_ssh_key`: %+v", err)
}
}
Expand Down
52 changes: 46 additions & 6 deletions azurerm/internal/services/compute/ssh_keys.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package compute

import (
"bytes"
"crypto/rsa"
"encoding/base64"
"fmt"
"log"
"regexp"
"strings"

"golang.org/x/crypto/ssh"

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute"
"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
"golang.org/x/crypto/ssh"
)

func SSHKeysSchema(isVirtualMachine bool) *schema.Schema {
Expand All @@ -23,13 +26,15 @@ func SSHKeysSchema(isVirtualMachine bool) *schema.Schema {
Type: schema.TypeSet,
Optional: true,
ForceNew: isVirtualMachine,
Set: SSHKeySchemaHash,
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"public_key": {
Type: schema.TypeString,
Required: true,
ForceNew: isVirtualMachine,
ValidateFunc: ValidateSSHKey,
Type: schema.TypeString,
Required: true,
ForceNew: isVirtualMachine,
ValidateFunc: ValidateSSHKey,
DiffSuppressFunc: SSHKeyDiffSuppress,
},

"username": {
Expand Down Expand Up @@ -155,3 +160,38 @@ func ValidateSSHKey(i interface{}, k string) (warnings []string, errors []error)

return warnings, errors
}

func SSHKeyDiffSuppress(_, old, new string, _ *schema.ResourceData) bool {
oldNormalised, err := azure.NormaliseSSHKey(old)
if err != nil {
log.Printf("[DEBUG] error normalising ssh key %q: %+v", old, err)
return false
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
}

newNormalised, err := azure.NormaliseSSHKey(new)
if err != nil {
log.Printf("[DEBUG] error normalising ssh key %q: %+v", new, err)
return false
jackofallops marked this conversation as resolved.
Show resolved Hide resolved
}

if *oldNormalised == *newNormalised {
return true
}

return false
}

func SSHKeySchemaHash(v interface{}) int {
var buf bytes.Buffer

if m, ok := v.(map[string]interface{}); ok {
normalisedKey, err := azure.NormaliseSSHKey(m["public_key"].(string))
if err != nil {
log.Printf("[DEBUG] error normalising ssh key %q: %+v", m["public_key"].(string), err)
}
buf.WriteString(fmt.Sprintf("%s-", *normalisedKey))
buf.WriteString(fmt.Sprintf("%s", m["username"]))
}

return hashcode.String(buf.String())
}