diff --git a/pkg/deploy/assets/env-development.json b/pkg/deploy/assets/env-development.json index 1da1cb9fb5b..f7f11814013 100644 --- a/pkg/deploy/assets/env-development.json +++ b/pkg/deploy/assets/env-development.json @@ -296,7 +296,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgogICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzCiAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1mIENvbmZpZ3VyZSBmaXJld2FsbGQgZGVmYXVsdCB6b25lIHJ1bGVzCiAgICAgICAgLXUgQ29uZmlndXJlIHN5c3RlbWQgdW5pdCBmaWxlcyBmb3IgQVJPIFJQCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1hIG9wdGlvbnM9KCR7MTotfSkKICAgIGlmIFsgIiR7I29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKCWxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0icGZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgcCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfZG5mX3VwZGF0ZV9maWxlbmFtZT0nL2V0Yy9jcm9uLndlZWtseS9kbmZ1cGRhdGUnCglsb2NhbCAtciBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRuZiB1cGRhdGUgLXkiCgoJd3JpdGVfZmlsZSBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGVuYW1lIGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZSB0cnVlCgljaG1vZCAreCAiJGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZW5hbWUiCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwpjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCiAgICBsb2NhbCAtciBwcmVmaXg9Ii9ldGMvc3lzY3RsLmQiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lPSIkcHJlZml4LzAyLWRpc2FibGUtYWNjZXB0LXJhLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGU9Im5ldC5pcHY2LmNvbmYuYWxsLmFjY2VwdF9yYT0wIgoKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlbmFtZT0iJHByZWZpeC8wMS1kaXNhYmxlLWNvcmUuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlPSJrZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQogICAgIgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2NvcmVfZmlsZW5hbWUgZGlzYWJsZV9jb3JlX2ZpbGUgdHJ1ZQoKICAgIHN5c2N0bCAtLXN5c3RlbQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9InsKCSJhdXRocyI6IHsKCQlcIiR7UFJPWFlJTUFHRSUlLyp9XCI6IHsKCQkJXCJhdXRoXCI6IFwiJFBST1hZSU1BR0VBVVRIXCIKCQl9Cgl9IgoKCXdyaXRlX2ZpbGUgUkVHSVNUUllfQVVUSF9GSUxFIHJlZ2lzdHJ5X2NvbmZpZ19maWxlIHRydWUKCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojCXByb3h5CmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7Cgljb25maWd1cmVfc2VydmljZV9wcm94eQp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQogICAgbG9nICJlbmFibGluZyBhcm8gc2VydmljZXMgJHthcm9fc2VydmljZXNbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2VydmljZSBpbiAke2Fyb19zZXJ2aWNlc1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyAkc2VydmljZSBub3ciCiAgICAgICAgc3lzdGVtY3RsIGVuYWJsZSAiJHNlcnZpY2Uuc2VydmljZSIKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCgliYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydAoJYmFzZTY0IC1kIDw8PCIkUFJPWFlLRVkiID4vZXRjL3Byb3h5L3Byb3h5LmtleQoJYmFzZTY0IC1kIDw8PCIkUFJPWFlDTElFTlRDRVJUIiA+L2V0Yy9wcm94eS9wcm94eS1jbGllbnQuY3J0CgljaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQoJY2htb2QgMDYwMCAvZXRjL3Byb3h5L3Byb3h5LmtleQp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRQUk9YWUlNQUdFJyIKCgl3cml0ZV9maWxlIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZSBzeXNjb25maWdfcHJveHlfZmlsZSB0cnVlCgoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9wcm94eS5zZXJ2aWNlJwoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9wcm94eQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlbgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biAtLXJtIC0tbmFtZSAlbiAtcCA0NDM6ODQ0MyAtdiAvZXRjL3Byb3h5Oi9zZWNyZXRzICRQUk9YWV9JTUFHRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlbgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lPScvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UnCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRvY2tlciBwdWxsICRQUk9YWUlNQUdFCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGUgdHJ1ZQoJY2htb2QgK3ggIiRjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIgoKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZT0nL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHknCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZT0iIyEvYmluL2Jhc2gKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGUKCWNobW9kICt4ICIkY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIgp9CgojIHdyaXRlX2ZpbGUKIyBBcmdzCiMgMSkgZmlsZW5hbWUgLSBzdHJpbmcKIyAyKSBmaWxlX2NvbnRlbnRzIC0gc3RyaW5nCiMgMykgY2xvYmJlciAtIGJvb2xlYW47IG9wdGlvbmFsIC0gZGVmYXVsdHMgdG8gZmFsc2UKd3JpdGVfZmlsZSgpIHsKICAgIGxvY2FsIC1uIGZpbGVuYW1lPSIkMSIKICAgIGxvY2FsIC1uIGZpbGVfY29udGVudHM9IiQyIgogICAgbG9jYWwgLXIgY2xvYmJlcj0iJHszOi1mYWxzZX0iCgogICAgaWYgJGNsb2JiZXI7IHRoZW4KICAgICAgICBsb2cgIk92ZXJ3cml0aW5nIGZpbGUgJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+ICIkZmlsZW5hbWUiCiAgICBlbHNlCiAgICAgICAgbG9nICJBcHBlbmRpbmcgdG8gJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+PiAiJGZpbGVuYW1lIgogICAgZmkKfQoKIyByZWJvb3Rfdm0gcmVzdG9yZXMgYWxsIHNlbGludXggZmlsZSBjb250ZXh0cywgd2FpdHMgMzAgc2Vjb25kcyB0aGVuIHJlYm9vdHMKcmVib290X3ZtKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBjb25maWd1cmVfc2VsaW51eCAidHJ1ZSIKICAgIChzbGVlcCAzMCAmJiBsb2cgInJlYm9vdGluZyB2bSBub3ciOyByZWJvb3QpICYKfQoKIyBsb2cgaXMgYSB3cmFwcGVyIGZvciBlY2hvIHRoYXQgaW5jbHVkZXMgdGhlIGZ1bmN0aW9uIG5hbWUKbG9nKCkgewogICAgbG9jYWwgLXIgbXNnPSIkezE6LSJsb2cgbWVzc2FnZSBpcyBlbXB0eSJ9IgogICAgbG9jYWwgLXIgc3RhY2tfbGV2ZWw9IiR7MjotMX0iCiAgICBlY2hvICIke0ZVTkNOQU1FWyR7c3RhY2tfbGV2ZWx9XX06ICR7bXNnfSIKfQoKIyBhYm9ydCBpcyBhIHdyYXBwZXIgZm9yIGxvZyB0aGF0IGV4aXRzIHdpdGggYW4gZXJyb3IgY29kZQphYm9ydCgpIHsKICAgIGxvY2FsIC1yaSBvcmlnaW5fc3RhY2tsZXZlbD0yCiAgICBsb2cgIiR7MX0iICIkb3JpZ2luX3N0YWNrbGV2ZWwiCiAgICBsb2cgIkV4aXRpbmciCiAgICBleGl0IDEKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb25WTVNTLnNoCiAgICBzb3VyY2UgY29tbW9uVk1TUy5zaAoKICAgIGNyZWF0ZV9yZXF1aXJlZF9kaXJzCgogICAgbG9jYWwgLWFyIGV4Y2x1ZGVfcGtncz0oCiAgICAgICAgIi14IFdBTGludXhBZ2VudCIKICAgICAgICAiLXggV0FMaW51eEFnZW50LXVkZXYiCiAgICApCgogICAgZG5mX3VwZGF0ZV9wa2dzIHBrZ3NfdG9fZXhjbHVkZSByZXRyeV93YWl0X3RpbWUKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCiAgICBjb25maWd1cmVfZG5mX2Nyb25fam9iCgogICAgbG9jYWwgLXJhIGVuYWJsZV9wb3J0cz0oCiAgICAgICAgIjQ0My90Y3AiCiAgICApCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBlbmFibGVfcG9ydHMKCiAgICBsb2NhbCAtcmEgcHJveHlfaW1hZ2VzPSgiJFBST1hZSU1BR0UiKQoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9InsKICAgIFwiYXV0aHNcIjogewogICAgICAgIFwiJHtwcm94eV9pbWFnZXNbMF0lJS8qfVwiOiB7CiAgICAgICAgICAgIFwiYXV0aFwiOiBcIiRQUk9YWUlNQUdFQVVUSFwiCiAgICAgICAgfQogICAgfQp9IgoKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBwcm94eV9pbWFnZSByZWdpc3RyeV9jb25maWdfZmlsZSBmYWxzZQogICAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzIHByb3h5X2ltYWdlcwoKICAgIGxvY2FsIC1yIHZtc3Nfcm9sZT0iZGV2cHJveHkiCiAgICBjb25maWd1cmVfY2VydHMgdm1zc19yb2xlCgogICAgbG9jYWwgLXJhIHByb3h5X3NlcnZpY2VzPSgKICAgICAgICBwcm94eQogICAgKQoKICAgIGVuYWJsZV9zZXJ2aWNlcyBwcm94eV9zZXJ2aWNlcwogICAgcmVib290X3ZtCn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMJcHJveHkKY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzKCkgewoJY29uZmlndXJlX3NlcnZpY2VfcHJveHkgIiQxIgp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKICAgIGxvY2FsIC1uIHByb3h5X2ltYWdlPSIkMSIKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRwcm94eV9pbWFnZSciCgoJd3JpdGVfZmlsZSBzeXNjb25maWdfcHJveHlfZmlsZW5hbWUgc3lzY29uZmlnX3Byb3h5X2ZpbGUgdHJ1ZQoKCWxvY2FsIC1yIHByb3h5X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vcHJveHkuc2VydmljZScKCWxvY2FsIC1yIHByb3h5X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvcHJveHkKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJW4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gLS1ybSAtLW5hbWUgJW4gLXAgNDQzOjg0NDMgLXYgL2V0Yy9wcm94eTovc2VjcmV0cyAkcHJveHlfaW1hZ2UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJW4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBwcm94eV9zZXJ2aWNlX2ZpbGVuYW1lIHByb3h5X3NlcnZpY2VfZmlsZSB0cnVlCgoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZT0nL2V0Yy9jcm9uLndlZWtseS9wdWxsLWltYWdlJwoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlPSIjIS9iaW4vYmFzaApkb2NrZXIgcHVsbCAkcHJveHlfaW1hZ2UKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIGNyb25fd2Vla2x5X3B1bGxfaW1hZ2VfZmlsZSB0cnVlCgljaG1vZCAreCAiJGNyb25fd2Vla2x5X3B1bGxfaW1hZ2VfZmlsZW5hbWUiCgoJbG9jYWwgLXIgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lPScvZXRjL2Nyb24uZGFpbHkvcmVzdGFydC1wcm94eScKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlPSIjIS9iaW4vYmFzaApzeXN0ZW1jdGwgcmVzdGFydCBwcm94eS5zZXJ2aWNlIgoJCgl3cml0ZV9maWxlIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZSB0cnVlCgljaG1vZCAreCAiJGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZSIKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" }, "provisionAfterExtensions": [ "Microsoft.Azure.Monitor.AzureMonitorLinuxAgent", diff --git a/pkg/deploy/assets/gateway-production.json b/pkg/deploy/assets/gateway-production.json index ecbbe148c12..cb2264e7d80 100644 --- a/pkg/deploy/assets/gateway-production.json +++ b/pkg/deploy/assets/gateway-production.json @@ -309,7 +309,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBsb2NhbCAtciBnYXRld2F5X2xvZ2Rpcj0nL3Zhci9sb2cvYXJvLWdhdGV3YXknCiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiIGdhdGV3YXlfbG9nZGlyCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUgZ2F0ZXdheV9sb2dkaXIKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgZ2F0ZXdheV9sb2dkaXIKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlICIkMiIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHMpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NlbGludXgiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc2VsaW51eAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgcikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfc3NoZCIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9zc2hkCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBmKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICB1KQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHB1bGxfY29udGFpbmVyX2ltYWdlcyAmIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzICIkMiIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGkpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzIgogICAgICAgICAgICAgICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgKikKICAgICAgICAgICAgICAgIHVzYWdlIGFsbG93ZWRfb3B0aW9ucwogICAgICAgICAgICAgICAgYWJvcnQgIlVua293biBvcHRpb24gcHJvdmlkZWQiCiAgICAgICAgICAgICAgICA7OwogICAgICAgIGVzYWMKICAgIGRvbmUKICAgIAogICAgZXhpdCAwCn0KCiMgV2UgbmVlZCB0byBjb25maWd1cmUgUGFzc3dvcmRBdXRoZW50aWNhdGlvbiB0byB5ZXMgaW4gb3JkZXIgZm9yIHRoZSBWTVNTIEFjY2VzcyBKSVQgdG8gd29yawpjb25maWd1cmVfc3NoZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgogICAgc2VkIC1pICdzL1Bhc3N3b3JkQXV0aGVudGljYXRpb24gbm8vUGFzc3dvcmRBdXRoZW50aWNhdGlvbiB5ZXMvZycgL2V0Yy9zc2gvc3NoZF9jb25maWcKCiAgICBzeXN0ZW1jdGwgcmVsb2FkIHNzaGQuc2VydmljZQogICAgc3lzdGVtY3RsIGlzLWFjdGl2ZSAtLXF1aWV0IHNzaGQgfHwgYWJvcnQgInNzaGQgZmFpbGVkIHRvIHJlbG9hZCIKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQogICAgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyByZXRyeV93YWl0X3RpbWUKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBkbmZfdXBkYXRlX3BrZ3MgZXhjbHVkZV9wa2dzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSBycG1fa2V5cz0oCiAgICAgICAgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKICAgICAgICBodHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20va2V5cy9taWNyb3NvZnQuYXNjCiAgICApCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgbG9jYWwgLXJhIGluc3RhbGxfcGtncz0oCiAgICAgICAgY2xhbWF2CiAgICAgICAgYXpzZWMtY2xhbWF2CiAgICAgICAgYXpzZWMtbW9uaXRvcgogICAgICAgIGF6dXJlLWNsaQogICAgICAgIGF6dXJlLW1kc2QKICAgICAgICBhenVyZS1zZWN1cml0eQogICAgICAgIHBvZG1hbgogICAgICAgIHBvZG1hbi1kb2NrZXIKICAgICAgICBvcGVuc3NsLXBlcmwKICAgICAgICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgICAgICAgcHl0aG9uMwogICAgKQoKICAgIGRuZl9pbnN0YWxsX3BrZ3MgcmVwb19ycG1fcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGRuZl9pbnN0YWxsX3BrZ3MgaW5zdGFsbF9wa2dzIHJldHJ5X3dhaXRfdGltZQp9CgojIGNvbmZpZ3VyZV9yaHVpX3JlcG8KY29uZmlndXJlX3JodWlfcmVwbygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgdXBkYXRlCiAgICAgICAgLXkKICAgICAgICAtLWRpc2FibGVyZXBvPScqJwogICAgICAgIC0tZW5hYmxlcmVwbz0ncmh1aS1taWNyb3NvZnQtYXp1cmUqJwogICAgKQoKICAgIGxvZyAicnVubmluZyBSSFVJIHBhY2thZ2UgdXBkYXRlcyIKICAgIHJldHJ5IGNtZCAiJDEiCn0KCiMgcmV0cnkgQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKcmV0cnkoKSB7CiAgICBsb2NhbCAtbiBjbWRfcmV0cnk9IiQxIgogICAgbG9jYWwgLW4gd2FpdF90aW1lPSIkMiIKCiAgICBmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgICAgICAgbG9nICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gJHtGVU5DTkFNRVsyXX0iCiAgICAgICAgJHtjbWRfcmV0cnlbQF19ICYKCiAgICAgICAgd2FpdCAkISAmJiBicmVhawogICAgICAgIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4KICAgICAgICAgICAgc2xlZXAgIiR3YWl0X3RpbWUiCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiYXR0ZW1wdCAjJHthdHRlbXB0fSAtIEZhaWxlZCB0byB1cGRhdGUgcGFja2FnZXMiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKIyBkbmZfdXBkYXRlX3BrZ3MKZG5mX3VwZGF0ZV9wa2dzKCkgewogICAgbG9jYWwgLW4gZXhjbHVkZXM9IiQxIgogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICAteQogICAgICAgICR7ZXhjbHVkZXNbQF19CiAgICAgICAgdXBkYXRlCiAgICAgICAgLS1hbGxvd2VyYXNpbmcKICAgICkKCiAgICBsb2cgIlVwZGF0aW5nIGFsbCBwYWNrYWdlcyIKICAgIHJldHJ5IGNtZCAiJDIiCn0KCiMgZG5mX2luc3RhbGxfcGtncwpkbmZfaW5zdGFsbF9wa2dzKCkgewogICAgbG9jYWwgLW4gcGtncz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgaW5zdGFsbAogICAgICAgICR7cGtnc1tAXX0KICAgICkKCiAgICBsb2cgIkF0dGVtcHRpbmcgdG8gaW5zdGFsbCBwYWNrYWdlczogJHtwa2dzWypdfSIKICAgIHJldHJ5IGNtZCAiJDIiCn0KCiMgcnBtX2ltcG9ydF9rZXlzCnJwbV9pbXBvcnRfa2V5cygpIHsKICAgIGxvY2FsIC1uIGtleXM9IiQxIgogICAgbG9nICJzdGFydGluZyIKCgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Iga2V5IGluICR7a2V5c1tAXX07IGRvCiAgICAgICAgaWYgWyAkeyNrZXlzW0BdfSAtZXEgMCBdOyB0aGVuCiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgZmkKICAgICAgICAgICAgbG9jYWwgLWEgY21kPSgKICAgICAgICAgICAgICAgIHJwbQogICAgICAgICAgICAgICAgLS1pbXBvcnQKICAgICAgICAgICAgICAgIC12CiAgICAgICAgICAgICAgICAiJGtleSIKICAgICAgICAgICAgKQoKICAgICAgICAgICAgbG9nICJhdHRlbXB0ICMkYXR0ZW1wdCAtIGltcG9ydGluZyBycG0gcmVwb3NpdG9yeSBrZXkgJGtleSIKICAgICAgICAgICAgcmV0cnkgY21kICIkMiIgJiYgdW5zZXQga2V5CiAgICBkb25lCn0KCiMgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwpjb25maWd1cmVfZGlza19wYXJ0aXRpb25zKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiZXh0ZW5kaW5nIHBhcnRpdGlvbiB0YWJsZSIKCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCiAgICBncm93cGFydCAiJHBoeXNpY2FsX2Rpc2siIDIKCiAgICBsb2cgImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKICAgIGxvZyAiZXh0ZW5kaW5nIHJvb3QgbHZtIgogICAgbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2CiAgICBsb2cgImdyb3dpbmcgcm9vdCBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvCgogICAgbG9nICJleHRlbmRpbmcgdmFyIGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsxMDAlRlJFRSAvZGV2L3Jvb3R2Zy92YXJsdgogICAgbG9nICJncm93aW5nIHZhciBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvdmFyCn0KCiMgY29uZmlndXJlX2xvZ3JvdGF0ZSBjbG9iYmVycyAvZXRjL2xvZ3JvdGF0ZS5jb25mCmNvbmZpZ3VyZV9sb2dyb3RhdGUoKSB7CiAgICBsb2NhbCAtbiBsb2dfZGlyPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPSIjIHNlZSAnbWFuIGxvZ3JvdGF0ZScgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9CgojIE1heGltdW0gbG9nIGRpcmVjdG9yeSBzaXplIGlzIDEwMEcgd2l0aCB0aGlzIGNvbmZpZ3VyYXRpb24KIyBTZXR0aW5nIGxpbWl0IHRvIDEwMEcgdG8gYWxsb3cgc3BhY2UgZm9yIG90aGVyIGxvZ2dpbmcgc2VydmljZXMKIyBjb3B5dHJ1bmNhdGUgaXMgYSBjcml0aWNhbCBvcHRpb24gdXNlZCB0byBwcmV2ZW50IGxvZ3MgZnJvbSBiZWluZyBzaGlwcGVkIHR3aWNlCiR7bG9nX2Rpcn0gewogICAgc2l6ZSAyMEcKICAgIHJvdGF0ZSA1CiAgICBjcmVhdGUgMDYwMCByb290IHJvb3QKICAgIGNvcHl0cnVuY2F0ZQogICAgbm9vbGRkaXIKICAgIGNvbXByZXNzCn0iCgogICAgd3JpdGVfZmlsZSBsb2dyb3RhdGVfY29uZl9maWxlbmFtZSBsb2dyb3RhdGVfY29uZl9maWxlIHRydWUKfQoKIyBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIGNyZWF0ZXMgL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIHJlcG9zaXRvcnkgZmlsZQpjcmVhdGVfYXp1cmVfcnBtX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGVuYW1lPScvZXRjL3l1bS5yZXBvcy5kL2F6dXJlLnJlcG8nCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGU9J1thenVyZS1jbGldCm5hbWU9YXp1cmUtY2xpCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlLWNsaQplbmFibGVkPXllcwpncGdjaGVjaz15ZXMKClthenVyZWNvcmVdCm5hbWU9YXp1cmVjb3JlCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlY29yZQplbmFibGVkPXllcwpncGdjaGVjaz1ubycKCiAgICB3cml0ZV9maWxlIGF6dXJlX3JlcG9fZmlsZW5hbWUgYXp1cmVfcmVwb19maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VsaW51eApjb25maWd1cmVfc2VsaW51eCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgcmVsYWJlbD0iJHsxOi1mYWxzZX0iCgogICAgYWxyZWFkeV9kZWZpbmVkX2lnbm9yZV9lcnJvcj0iRmlsZSBjb250ZXh0IGZvciAvdmFyL2xvZy9qb3VybmFsKC8uKik/IGFscmVhZHkgZGVmaW5lZCIKICAgIHNlbWFuYWdlIGZjb250ZXh0IC1hIC10IHZhcl9sb2dfdCAiL3Zhci9sb2cvam91cm5hbCgvLiopPyIgfHwgbG9nICIkYWxyZWFkeV9kZWZpbmVkX2lnbm9yZV9lcnJvciIKICAgIGNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKICAgIGlmICIkcmVsYWJlbCI7IHRoZW4KICAgICAgICByZXN0b3JlY29uIC1SRiAvdmFyL2xvZy8qIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBmaQp9CgojIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMKY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgIyBodHRwczovL2FjY2Vzcy5yZWRoYXQuY29tL3NlY3VyaXR5L2N2ZS9jdmUtMjAyMC0xMzQwMQogICAgbG9jYWwgLXIgcHJlZml4PSIvZXRjL3N5c2N0bC5kIgogICAgbG9jYWwgLXIgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZT0iJHByZWZpeC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlPSJuZXQuaXB2Ni5jb25mLmFsbC5hY2NlcHRfcmE9MCIKCiAgICB3cml0ZV9maWxlIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBkaXNhYmxlX2NvcmVfZmlsZW5hbWU9IiRwcmVmaXgvMDEtZGlzYWJsZS1jb3JlLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2NvcmVfZmlsZT0ia2VybmVsLmNvcmVfcGF0dGVybiA9IHwvYmluL3RydWUKICAgICIKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lIGRpc2FibGVfY29yZV9maWxlIHRydWUKCiAgICBzeXNjdGwgLS1zeXN0ZW0KCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiODAvdGNwIgogICAgICAgICI4MDgxL3RjcCIKICAgICAgICAiNDQzL3RjcCIKICAgICkKCiAgICBsb2cgIkVuYWJsaW5nIHBvcnRzICR7ZW5hYmxlX3BvcnRzWypdfSBvbiBkZWZhdWx0IGZpcmV3YWxsZCB6b25lIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3IgcG9ydCBpbiAke2VuYWJsZV9wb3J0c1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyBwb3J0ICRwb3J0IG5vdyIKICAgICAgICBmaXJld2FsbC1jbWQgIi0tYWRkLXBvcnQ9JHBvcnQiCiAgICBkb25lCgogICAgZmlyZXdhbGwtY21kIC0tcnVudGltZS10by1wZXJtYW5lbnQKfQoKIyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKcHVsbF9jb250YWluZXJfaW1hZ2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiAgICAjIFRoaXMgcm9sZSBhc3NpZ25tZW50IGlzIEFDUlB1bGwgd2hpY2ggaXMgbm90IG5lY2Vzc2FyaWx5IHByZXNlbnQgaW4gdGhlCiAgICAjIHN1YnNjcmlwdGlvbiB3ZSdyZSBkZXBsb3lpbmcgaW50by4gIElmIHRoZSBpZGVudGl0eSBkb2VzIG5vdCBoYXZlIGFueQogICAgIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiAgICAjIG5vdCBzaG93IG9uIGF6IGxvZ2luIC1pLCB3aGljaCBpcyB3aHkgdGhlIGJlbG93IGxpbmUgaXMgY29tbWVudGVkLgogICAgIyBheiBhY2NvdW50IHNldCAtcyAiJFNVQlNDUklQVElPTklEIgogICAgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgogICAgIyBTdXBwcmVzcyBlbXVsYXRpb24gb3V0cHV0IGZvciBwb2RtYW4gaW5zdGVhZCBvZiBkb2NrZXIgZm9yIGF6IGFjciBjb21wYXRhYmlsaXR5CiAgICBta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCiAgICBta2RpciAtcCAvcm9vdC8uZG9ja2VyCiAgICB0b3VjaCAvZXRjL2NvbnRhaW5lcnMvbm9kb2NrZXIKCgkjIFRoaXMgbmFtZSBpcyB1c2VkIGluIHRoZSBjYXNlIHRoYXQgYXogYWNyIGxvZ2luIHNlYXJjaGVzIGZvciB0aGlzIGluIGl0J3MgZW52aXJvbm1lbnQKICAgIGxvY2FsIC1yIFJFR0lTVFJZX0FVVEhfRklMRT0iL3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiIKICAgIAogICAgbG9nICJsb2dnaW5nIGludG8gcHJvZCBhY3IiCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgTURNSU1BR0U9IiR7UlBJTUFHRSUlLyp9LyR7TURNSU1BR0UjIyovfSIKICAgIGRvY2tlciBwdWxsICIkTURNSU1BR0UiCiAgICBkb2NrZXIgcHVsbCAiJFJQSU1BR0UiCiAgICBkb2NrZXIgcHVsbCAiJEZMVUVOVEJJVElNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojICAgZmx1ZW50Yml0CiMgICBtZG0KIyAgIG1kc2QKIyAgIGFycC1ycAojICAgYXJvLWRidG9rZW4KIyAgIGFyby1tb25pdG9yCiMgICBhcm8tcG9ydGFsCmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7CiAgICBjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQogICAgY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZAogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX2dhdGV3YXkgIiQxIgogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgYXJvLWdhdGV3YXkKICAgICAgYXVvbXMKICAgICAgYXpzZWNkCiAgICAgIGF6c2VjbW9uZAogICAgICBtZHNkCiAgICAgIG1kbQogICAgICBjaHJvbnlkCiAgICAgIGZsdWVudGJpdAogICAgKQogICAgbG9nICJlbmFibGluZyBnYXRld2F5IHNlcnZpY2VzICR7YXJvX3NlcnZpY2VzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNlcnZpY2UgaW4gJHthcm9fc2VydmljZXNbQF19OyBkbwogICAgICAgIGxvZyAiRW5hYmxpbmcgJHNlcnZpY2Ugbm93IgogICAgICAgIHN5c3RlbWN0bCBlbmFibGUgIiRzZXJ2aWNlLnNlcnZpY2UiCiAgICBkb25lCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CmNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgoKICAgIG1rZGlyIC1wIC9ldGMvZmx1ZW50Yml0LwogICAgbWtkaXIgLXAgL3Zhci9saWIvZmx1ZW50CgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWU9Jy9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mJwogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZT0iW0lOUFVUXQpOYW1lIHN5c3RlbWQKVGFnIGpvdXJuYWxkClN5c3RlbWRfRmlsdGVyIF9DT01NPWFybwpEQiAvdmFyL2xpYi9mbHVlbnQvam91cm5hbGRiCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGpvdXJuYWxkCglSZW1vdmVfd2lsZGNhcmQgXwoJUmVtb3ZlIFRJTUVTVEFNUAoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdCcKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZT0iRkxVRU5UQklUSU1BR0U9JEZMVUVOVEJJVElNQUdFIgoKICAgIHdyaXRlX2ZpbGUgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlJwoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0ClN0YXJ0TGltaXRJbnRlcnZhbFNlYz0wCgpbU2VydmljZV0KUmVzdGFydFNlYz0xcwpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLXNlY3VyaXR5LW9wdCBsYWJlbD1kaXNhYmxlIFwKICAtLWVudHJ5cG9pbnQgL29wdC90ZC1hZ2VudC1iaXQvYmluL3RkLWFnZW50LWJpdCBcCiAgLS1uZXQ9aG9zdCBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC12IC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mOi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIFwKICAtdiAvdmFyL2xpYi9mbHVlbnQ6L3Zhci9saWIvZmx1ZW50OnogXAogIC12IC92YXIvbG9nL2pvdXJuYWw6L3Zhci9sb2cvam91cm5hbDpybyBcCiAgLXYgL2V0Yy9tYWNoaW5lLWlkOi9ldGMvbWFjaGluZS1pZDpybyBcCiAgJEZMVUVOVEJJVElNQUdFIFwKICAtYyAvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZgoKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz01ClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBmbHVlbnRiaXRfY29uZl9maWxlbmFtZSBmbHVlbnRiaXRfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBta2RpciAvZXRjL2Fyby1ycAogICAgYmFzZTY0IC1kIDw8PCIkQURNSU5BUElDQUJVTkRMRSIgPi9ldGMvYXJvLXJwL2FkbWluLWNhLWJ1bmRsZS5wZW0KICAgIGlmIFtbIC1uICIkQVJNQVBJQ0FCVU5ETEUiIF1dOyB0aGVuCiAgICBiYXNlNjQgLWQgPDw8IiRBUk1BUElDQUJVTkRMRSIgPi9ldGMvYXJvLXJwL2FybS1jYS1idW5kbGUucGVtCiAgICBmaQogICAgY2hvd24gLVIgMTAwMDoxMDAwIC9ldGMvYXJvLXJwCgogICAgIyBzZXR0aW5nIE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQgc2VlbXMgdG8gaGF2ZSBjYXVzZWQgbWRzZCBub3QKICAgICMgdG8gaG9ub3VyIFNTTF9DRVJUX0ZJTEUgYW55IG1vcmUsIGhlYXZlbiBvbmx5IGtub3dzIHdoeS4KICAgIG1rZGlyIC1wIC91c3IvbGliL3NzbC9jZXJ0cwogICAgY3NwbGl0IC1mIC91c3IvbGliL3NzbC9jZXJ0cy9jZXJ0LSAtYiAlMDNkLnBlbSAvZXRjL3BraS90bHMvY2VydHMvY2EtYnVuZGxlLmNydCAvXiQvMSAieyp9IiA+L2Rldi9udWxsCiAgICBjX3JlaGFzaCAvdXNyL2xpYi9zc2wvY2VydHMKCiMgd2UgbGVhdmUgY2xpZW50SWQgYmxhbmsgYXMgbG9uZyBhcyBvbmx5IDEgbWFuYWdlZCBpZGVudGl0eSBhc3NpZ25lZCB0byB2bXNzCiMgaWYgd2UgaGF2ZSBtb3JlIHRoYW4gMSwgd2Ugd2lsbCBuZWVkIHRvIHBvcHVsYXRlIHdpdGggY2xpZW50SWQgdXNlZCBmb3Igb2ZmLW5vZGUgc2Nhbm5pbmcKICAgIGxvY2FsIC1yIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvdnNhLW5vZGVzY2FuLWFnZW50LmNvbmZpZyIKICAgIGxvY2FsIC1yIG5vZGVzY2FuX2FnZW50X2ZpbGU9InsKICAgIFwiTmljZVwiOiAxOSwKICAgIFwiVGltZW91dFwiOiAxMDgwMCwKICAgIFwiQ2xpZW50SWRcIjogXCJcIiwKICAgIFwiVGVuYW50SWRcIjogJEFaVVJFU0VDUEFDS1ZTQVRFTkFOVElELAogICAgXCJRdWFseXNTdG9yZUJhc2VVcmxcIjogJEFaVVJFU0VDUEFDS1FVQUxZU1VSTCwKICAgIFwiUHJvY2Vzc1RpbWVvdXRcIjogMzAwLAogICAgXCJDb21tYW5kRGVsYXlcIjogMAogIH0iCgogICAgd3JpdGVfZmlsZSBub2Rlc2Nhbl9hZ2VudF9maWxlbmFtZSBub2Rlc2Nhbl9hZ2VudF9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZG0KY29uZmlndXJlX3NlcnZpY2VfbWRtKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiY29uZmlndXJpbmcgbWRtIHNlcnZpY2UiCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX21kbV9maWxlbmFtZT0iL2V0Yy9zeXNjb25maWcvbWRtIgogICAgbG9jYWwgLXIgc3lzY29uZmlnX21kbV9maWxlPSJNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPWdhdGV3YXkKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwiZ3d5LVwke0NPTVBPTkVOVH1cIgpORVdfQ0VSVF9GSUxFPVwiXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW1cIgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgYXoga2V5dmF1bHQgXAogICAgc2VjcmV0IFwKICAgIGRvd25sb2FkIFwKICAgIC0tZmlsZSBcIlwkTkVXX0NFUlRfRklMRVwiIFwKICAgIC0taWQgXCJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1nd3kuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRVwiIFwKICAgICYmIGJyZWFrCiAgaWYgW1sgXCRhdHRlbXB0IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKaWYgWyAtZiBcJE5FV19DRVJUX0ZJTEUgXTsgdGhlbgogIGlmIFtbIFwkQ09NUE9ORU5UID0gXCJtZHNkXCIgXV07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJE5FV19DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGN1cnJlbnRfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJENVUlJFTlRfQ0VSVF9GSUxFXCIgLW5vb3V0IC1zZXJpYWwgfCBhd2sgLUY9ICd7cHJpbnQgXCQyfScpXCIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSBcIlwkY3VycmVudF9jZXJ0X3NuXCIgXV07IHRoZW4KICAgIGVjaG8gdXBkYXRpbmcgY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UCiAgICBjaG1vZCAwNjAwIFwkTkVXX0NFUlRfRklMRQogICAgbXYgXCRORVdfQ0VSVF9GSUxFIFwkQ1VSUkVOVF9DRVJUX0ZJTEUKICBmaQplbHNlCiAgZWNobyBGYWlsZWQgdG8gcmVmcmVzaCBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQgJiYgZXhpdCAxCmZpIgoKICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlIHRydWUKCiAgICBjaG1vZCB1K3ggL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2gKCiAgICBzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kc2QtY3JlZGVudGlhbHMudGltZXIKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgogICAgL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRzZAogICAgL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRtCgogICAgbG9jYWwgLXIgTURTRENFUlRJRklDQVRFU0FOPSIkKG9wZW5zc2wgeDUwOSAtaW4gL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUvbWRzZC5wZW0gLW5vb3V0IC1zdWJqZWN0IHwgc2VkIC1lICdzLy4qQ04gPSAvLycpIgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnNlcnZpY2UiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249V2F0Y2ggZm9yIGNoYW5nZXMgaW4gbWRtLnBlbSBhbmQgcmVzdGFydHMgdGhlIG1kbSBzZXJ2aWNlCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2Jpbi9zeXN0ZW1jdGwgcmVzdGFydCBtZG0uc2VydmljZQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWUgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgnCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlPSdbUGF0aF0KUGF0aE1vZGlmaWVkPS9ldGMvbWRtLnBlbQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0JwoKICAgIHdyaXRlX2ZpbGUgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZW5hbWUgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzPSd3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIHN5c3RlbWN0bCBlbmFibGUgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gZW5hYmxlICR3YXRjaF9tZG1fY3JlZHMiCiAgICBzeXN0ZW1jdGwgc3RhcnQgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gc3RhcnQgJHdhdGNoX21kbV9jcmVkcyIKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKY29uZmlndXJlX3NlcnZpY2VfYXJvX2dhdGV3YXkoKSB7CiAgICBsb2NhbCAtbiBsb2dfZGlyPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2dhdGV3YXlfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXknCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9jb25mX2ZpbGU9IkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQVpVUkVfREJUT0tFTl9DTElFTlRfSUQ9JyREQlRPS0VOQ0xJRU5USUQnCkRCVE9LRU5fVVJMPSckREJUT0tFTlVSTCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9R2F0ZXdheQpHQVRFV0FZX0RPTUFJTlM9JyRHQVRFV0FZRE9NQUlOUycKR0FURVdBWV9GRUFUVVJFUz0nJEdBVEVXQVlGRUFUVVJFUycKR0FURVdBWV9SRVNPVVJDRUdST1VQPSckR0FURVdBWVJFU09VUkNFR1JPVVBOQU1FJwpLRVlWQVVMVF9QUkVGSVg9JyRLRVlWQVVMVFBSRUZJWCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9UlAKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKUlBfRkVBVFVSRVM9JyRSUEZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRScKQVJPX0lOU1RBTExfVklBX0hJVkU9JyRDTFVTVEVSU0lOU1RBTExWSUFISVZFJwpBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQz0nJENMVVNURVJERUZBVUxUSU5TVEFMTEVSUFVMTFNQRUMnCkFST19BRE9QVF9CWV9ISVZFPSckQ0xVU1RFUlNBRE9QVEJZSElWRScKVVNFX0NIRUNLQUNDRVNTPSckVVNFQ0hFQ0tBQ0NFU1MnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX2dhdGV3YXlfY29uZl9maWxlbmFtZSBhcm9fZ2F0ZXdheV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWdhdGV3YXkuc2VydmljZScKCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydFByZT0vdXNyL2Jpbi9ta2RpciAtcCAke2xvZ19kaXJ9CkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEIFwKICAtZSBEQlRPS0VOX1VSTCBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX0ZFQVRVUkVTIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDgwOjgwODAgXAogIC1wIDgwODE6ODA4MSBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAtdiAke2xvZ19kaXJ9Oi9jdHIubG9nOnogXAogIFwkUlBJTUFHRSBcCiAgZ2F0ZXdheQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKICAgICIKCiAgICB3cml0ZV9maWxlIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZW5hbWUgYXJvX2dhdGV3YXlfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKREJUT0tFTl9VUkw9JyREQlRPS0VOVVJMJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1HYXRld2F5CkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX0ZFQVRVUkVTPSckR0FURVdBWUZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWRidG9rZW4uc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXkKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0UHJlPS91c3IvYmluL21rZGlyIC1wICR7Z2F0ZXdheV9sb2dkaXJ9CkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEIFwKICAtZSBEQlRPS0VOX1VSTCBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX0ZFQVRVUkVTIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDgwOjgwODAgXAogIC1wIDgwODE6ODA4MSBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAtdiAke2dhdGV3YXlfbG9nZGlyfTovY3RyLmxvZzp6IFwKICBcJFJQSU1BR0UgXAogIGdhdGV3YXkKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgLXQgMzYwMCAlTgpUaW1lb3V0U3RvcFNlYz0zNjAwClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QKY29uZmlndXJlX3NlcnZpY2VfbWRzZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvbWRzZCIKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlPSJNRFNEX1JPTEVfUFJFRklYPS92YXIvcnVuL21kc2QvZGVmYXVsdApNRFNEX09QVElPTlM9XCItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVhcIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckR0FURVdBWU1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPWdhdGV3YXkKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb25WTVNTLnNoCiAgICBzb3VyY2UgY29tbW9uVk1TUy5zaAoKICAgIGNyZWF0ZV9yZXF1aXJlZF9kaXJzCiAgICBjb25maWd1cmVfc3NoZAogICAgY29uZmlndXJlX3JwbV9yZXBvcyByZXRyeV93YWl0X3RpbWUKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBkbmZfdXBkYXRlX3BrZ3MgcGtnc190b19leGNsdWRlIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSBycG1fa2V5cz0oCiAgICAgICAgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKICAgICAgICBodHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20va2V5cy9taWNyb3NvZnQuYXNjCiAgICApCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgY29uZmlndXJlX2RuZl9jcm9uX2pvYgoKICAgIGxvY2FsIC1yYSBpbnN0YWxsX3BrZ3M9KAogICAgICAgIGNsYW1hdgogICAgICAgIGF6c2VjLWNsYW1hdgogICAgICAgIGF6c2VjLW1vbml0b3IKICAgICAgICBhenVyZS1jbGkKICAgICAgICBhenVyZS1tZHNkCiAgICAgICAgYXp1cmUtc2VjdXJpdHkKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICAgICAgb3BlbnNzbC1wZXJsCiAgICAgICAgIyBoYWNrIC0gd2UgYXJlIGluc3RhbGxpbmcgcHl0aG9uMyBvbiBob3N0cyBkdWUgdG8gYW4gaXNzdWUgd2l0aCBBenVyZSBMaW51eCBFeHRlbnNpb25zIGh0dHBzOi8vZ2l0aHViLmNvbS9BenVyZS9henVyZS1saW51eC1leHRlbnNpb25zL3B1bGwvMTUwNQogICAgICAgIHB5dGhvbjMKICAgICkKCiAgICBkbmZfaW5zdGFsbF9wa2dzIGluc3RhbGxfcGtncyByZXRyeV93YWl0X3RpbWUKCiAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCgogICAgbG9jYWwgLXIgZ2F0ZXdheV9sb2dkaXI9Jy92YXIvbG9nL2Fyby1nYXRld2F5JwogICAgbG9jYWwgLXIgZ2F0ZXdheV9sb2dfZmlsZT0iIyBNYXhpbXVtIGxvZyBkaXJlY3Rvcnkgc2l6ZSBpcyAxMDBHIHdpdGggdGhpcyBjb25maWd1cmF0aW9uCiMgU2V0dGluZyBsaW1pdCB0byAxMDBHIHRvIGFsbG93IHNwYWNlIGZvciBvdGhlciBsb2dnaW5nIHNlcnZpY2VzCiMgY29weXRydW5jYXRlIGlzIGEgY3JpdGljYWwgb3B0aW9uIHVzZWQgdG8gcHJldmVudCBsb2dzIGZyb20gYmVpbmcgc2hpcHBlZCB0d2ljZQoke2xvZ19kaXJ9IHsKICAgIHNpemUgMjBHCiAgICByb3RhdGUgNQogICAgY3JlYXRlIDA2MDAgcm9vdCByb290CiAgICBjb3B5dHJ1bmNhdGUKICAgIG5vb2xkZGlyCiAgICBjb21wcmVzcwp9IgoKICAgICMgS2V5IGRpY3RhdGVzIHRoZSBmaWxlbmFtZSB3cml0dGVuIGluIC9ldGMvbG9ncm90YXRlLmQKICAgIGxvY2FsIC1yQSBsb2dyb3RhdGVfZHJvcGlucz0oCiAgICAgICAgWyJnYXRld2F5Il09IiRnYXRld2F5X2xvZ19maWxlIgogICAgKQoKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUgbG9ncm90YXRlX2Ryb3BpbnMKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbG9jYWwgLXJhIGVuYWJsZV9wb3J0cz0oCiAgICAgICAgIjgwL3RjcCIKICAgICAgICAiODA4MS90Y3AiCiAgICAgICAgIjQ0My90Y3AiCiAgICApCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIGVuYWJsZV9wb3J0cwoKICAgIGxvY2FsIC1yIG1kbWltYWdlPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCiAgICBsb2NhbCAtciBycGltYWdlPSIkUlBJTUFHRSIKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9pbWFnZT0iJEZMVUVOVEJJVElNQUdFIgogICAgbG9jYWwgLXJhIGltYWdlcz0oCiAgICAgICAgIiRtZG1pbWFnZSIKICAgICAgICAiJHJwaW1hZ2UiCiAgICAgICAgIiRmbHVlbnRiaXRfaW1hZ2UiCiAgICApCgogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIGltYWdlcyByZWdpc3RyeV9jb25maWdfZmlsZQoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltPVVRQVVRdCglOYW1lIGZvcndhcmQKCU1hdGNoICoKCVBvcnQgMjkyMzAiCgogICAgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0IGZsdWVudGJpdF9jb25mX2ZpbGUgZmx1ZW50Yml0X2ltYWdlCiAgICBsb2NhbCAtciBtZG1fcm9sZT0iZ2F0ZXdheSIKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbSBtZG1fcm9sZSBtZG1pbWFnZQoKICAgIGxvY2FsIC1yIGd3eV9kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQVpVUkVfREJUT0tFTl9DTElFTlRfSUQ9JyREQlRPS0VOQ0xJRU5USUQnCkRCVE9LRU5fVVJMPSckREJUT0tFTlVSTCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9R2F0ZXdheQpHQVRFV0FZX0RPTUFJTlM9JyRHQVRFV0FZRE9NQUlOUycKR0FURVdBWV9GRUFUVVJFUz0nJEdBVEVXQVlGRUFUVVJFUycKUlBJTUFHRT0nJFJQSU1BR0UnIgogICAgY29uZmlndXJlX3NlcnZpY2VfZ2F0ZXdheSBnYXRld2F5X2xvZ2RpcgoKICAgIGxvY2FsIC1yIG1kc2RfY29uZmlnX3ZlcnNpb249IiRHQVRFV0FZTURTRENPTkZJR1ZFUlNJT04iCiAgICBjb25maWd1cmVfc2VydmljZV9tZHNkIG1kbV9yb2xlIG1kc2RfY29uZmlnX3ZlcnNpb24KICAgIGxvY2FsIC1yIG1kc2Rfcm9sZT0iZ3d5IgogICAgY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZCBtZHNkX3JvbGUKCiAgICBjb25maWd1cmVfY2VydHMgbWRtX3JvbGUKCiAgICBsb2NhbCAtcmEgZ2F0ZXdheV9zZXJ2aWNlcz0oCiAgICAgICAgImFyby1nYXRld2F5IgogICAgICAgICJhdW9tcyIKICAgICAgICAiYXpzZWNkIgogICAgICAgICJhenNlY21vbmQiCiAgICAgICAgIm1kc2QiCiAgICAgICAgIm1kbSIKICAgICAgICAiY2hyb255ZCIKICAgICAgICAiZmx1ZW50Yml0IgogICAgICAgICJkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyIgogICAgICAgICJkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIiCiAgICApCgogICAgZW5hYmxlX3NlcnZpY2VzIGdhdGV3YXlfc2VydmljZXMKCiAgICByZWJvb3Rfdm0KfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKY29uZmlndXJlX3NlcnZpY2VfZ2F0ZXdheSgpIHsKICAgIGxvY2FsIC1uIGxvZ19kaXI9IiQxIgogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZ2F0ZXdheScKICAgIGxvY2FsIC1yIGFyb19nYXRld2F5X2NvbmZfZmlsZT0iQUNSX1JFU09VUkNFX0lEPSckQUNSUkVTT1VSQ0VJRCcKQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQURNSU5BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVJNX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFSTUFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBWlVSRV9BUk1fQ0xJRU5UX0lEPSckQVJNQ0xJRU5USUQnCkFaVVJFX0ZQX0NMSUVOVF9JRD0nJEZQQ0xJRU5USUQnCkFaVVJFX0ZQX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckRlBTRVJWSUNFUFJJTkNJUEFMSUQnCkJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRD0nJEJJTExJTkdFMkVTVE9SQUdFQUNDT1VOVElEJwpDTFVTVEVSX01ETV9BQ0NPVU5UPSckQ0xVU1RFUk1ETUFDQ09VTlQnCkNMVVNURVJfTURNX05BTUVTUEFDRT1SUApDTFVTVEVSX01EU0RfQUNDT1VOVD0nJENMVVNURVJNRFNEQUNDT1VOVCcKQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OPSckQ0xVU1RFUk1EU0RDT05GSUdWRVJTSU9OJwpDTFVTVEVSX01EU0RfTkFNRVNQQUNFPSckQ0xVU1RFUk1EU0ROQU1FU1BBQ0UnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkRPTUFJTl9OQU1FPSckTE9DQVRJT04uJENMVVNURVJQQVJFTlRET01BSU5OQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKREJUT0tFTl9VUkw9JyREQlRPS0VOVVJMJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1HYXRld2F5CkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX0ZFQVRVUkVTPSckR0FURVdBWUZFQVRVUkVTJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fZ2F0ZXdheV9jb25mX2ZpbGVuYW1lIGFyb19nYXRld2F5X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2dhdGV3YXlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZ2F0ZXdheS5zZXJ2aWNlJwoKICAgIGxvY2FsIC1yIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXkKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0UHJlPS91c3IvYmluL21rZGlyIC1wICR7bG9nX2Rpcn0KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtZSBBQ1JfUkVTT1VSQ0VfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIERCVE9LRU5fVVJMIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfRkVBVFVSRVMgXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyZyBcCiAgLXAgODA6ODA4MCBcCiAgLXAgODA4MTo4MDgxIFwKICAtcCA0NDM6ODQ0MyBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogIC12ICR7bG9nX2Rpcn06L2N0ci5sb2c6eiBcCiAgJFJQSU1BR0UgXAogIGdhdGV3YXkKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgLXQgMzYwMCAlTgpUaW1lb3V0U3RvcFNlYz0zNjAwClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CiAgICAiCgogICAgd3JpdGVfZmlsZSBhcm9fZ2F0ZXdheV9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZSB0cnVlCn0KCmV4cG9ydCBBWlVSRV9DTE9VRF9OQU1FPSIke0FaVVJFQ0xPVUROQU1FOj8iRmFpbGVkIHRvIGNhcnJ5IG92ZXIgdmFyaWFibGVzIn0iCgptYWluICIkQCIK')))]" } } } diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index 99f72f4d6ff..740e15c2359 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -516,7 +516,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBzKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9zZWxpbnV4IgogICAgICAgICAgICAgICAgY29uZmlndXJlX3NlbGludXgKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHIpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NzaGQiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3NoZAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBXZSBuZWVkIHRvIGNvbmZpZ3VyZSBQYXNzd29yZEF1dGhlbnRpY2F0aW9uIHRvIHllcyBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCmNvbmZpZ3VyZV9zc2hkKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAic2V0dGluZyBzc2ggcGFzc3dvcmQgYXV0aGVudGljYXRpb24iCiAgICBzZWQgLWkgJ3MvUGFzc3dvcmRBdXRoZW50aWNhdGlvbiBuby9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIHllcy9nJyAvZXRjL3NzaC9zc2hkX2NvbmZpZwoKICAgIHN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCiAgICBzeXN0ZW1jdGwgaXMtYWN0aXZlIC0tcXVpZXQgc3NoZCB8fCBhYm9ydCAic3NoZCBmYWlsZWQgdG8gcmVsb2FkIgp9CgojIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwpjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgdHJhbnNhY3Rpb24gYXR0ZW1wdCByZXRyeSB0aW1lIGluIHNlY29uZHMKICAgIGxvY2FsIC1yaSByZXRyeV93YWl0X3RpbWU9NjAKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8gcmV0cnlfd2FpdF90aW1lCiAgICBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJwbV9rZXlzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOAogICAgICAgIGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKICAgICkKCiAgICBycG1faW1wb3J0X2tleXMgcnBtX2tleXMgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBjbGFtYXYKICAgICAgICBhenNlYy1jbGFtYXYKICAgICAgICBhenNlYy1tb25pdG9yCiAgICAgICAgYXp1cmUtY2xpCiAgICAgICAgYXp1cmUtbWRzZAogICAgICAgIGF6dXJlLXNlY3VyaXR5CiAgICAgICAgcG9kbWFuCiAgICAgICAgcG9kbWFuLWRvY2tlcgogICAgICAgIG9wZW5zc2wtcGVybAogICAgICAgICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICAgICAgICBweXRob24zCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBycG1faW1wb3J0X2tleXMKcnBtX2ltcG9ydF9rZXlzKCkgewogICAgbG9jYWwgLW4ga2V5cz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBrZXkgaW4gJHtrZXlzW0BdfTsgZG8KICAgICAgICBpZiBbICR7I2tleXNbQF19IC1lcSAwIF07IHRoZW4KICAgICAgICAgICAgYnJlYWsKICAgICAgICBmaQogICAgICAgICAgICBsb2NhbCAtYSBjbWQ9KAogICAgICAgICAgICAgICAgcnBtCiAgICAgICAgICAgICAgICAtLWltcG9ydAogICAgICAgICAgICAgICAgLXYKICAgICAgICAgICAgICAgICIka2V5IgogICAgICAgICAgICApCgogICAgICAgICAgICBsb2cgImF0dGVtcHQgIyRhdHRlbXB0IC0gaW1wb3J0aW5nIHJwbSByZXBvc2l0b3J5IGtleSAka2V5IgogICAgICAgICAgICByZXRyeSBjbWQgIiQyIiAmJiB1bnNldCBrZXkKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJleHRlbmRpbmcgcGFydGl0aW9uIHRhYmxlIgoKICAgICMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKICAgICMgaXQncyBkaWZmaWN1bHQgdG8gdGllIHRoZSBsdm0gcHYgdG8gdGhlIHBoeXNpY2FsIGRpc2sgdXNpbmcgL2Rldi9kaXNrIGZpbGVzLCB3aGljaCBpcyB3aHkgbHZzIGlzIHVzZWQgaGVyZQogICAgcGh5c2ljYWxfZGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKICAgIGxvZyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgogICAgbG9nICJleHRlbmRpbmcgcm9vdCBsdm0iCiAgICBsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKICAgIGxvZyAiZ3Jvd2luZyByb290IGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC8KCiAgICBsb2cgImV4dGVuZGluZyB2YXIgbHZtIgogICAgbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2CiAgICBsb2cgImdyb3dpbmcgdmFyIGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC92YXIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlbmFtZT0nL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvJwogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlPSdbYXp1cmUtY2xpXQpuYW1lPWF6dXJlLWNsaQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZS1jbGkKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9eWVzCgpbYXp1cmVjb3JlXQpuYW1lPWF6dXJlY29yZQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZWNvcmUKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9bm8nCgogICAgd3JpdGVfZmlsZSBhenVyZV9yZXBvX2ZpbGVuYW1lIGF6dXJlX3JlcG9fZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlbGludXgKY29uZmlndXJlX3NlbGludXgoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIHJlbGFiZWw9IiR7MTotZmFsc2V9IgoKICAgIGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3I9IkZpbGUgY29udGV4dCBmb3IgL3Zhci9sb2cvam91cm5hbCgvLiopPyBhbHJlYWR5IGRlZmluZWQiCiAgICBzZW1hbmFnZSBmY29udGV4dCAtYSAtdCB2YXJfbG9nX3QgIi92YXIvbG9nL2pvdXJuYWwoLy4qKT8iIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCiAgICBpZiAiJHJlbGFiZWwiOyB0aGVuCiAgICAgICAgcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKiB8fCBsb2cgIiRhbHJlYWR5X2RlZmluZWRfaWdub3JlX2Vycm9yIgogICAgZmkKfQoKIyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCmNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgaHR0cHM6Ly9hY2Nlc3MucmVkaGF0LmNvbS9zZWN1cml0eS9jdmUvY3ZlLTIwMjAtMTM0MDEKICAgIGxvY2FsIC1yIHByZWZpeD0iL2V0Yy9zeXNjdGwuZCIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWU9IiRwcmVmaXgvMDItZGlzYWJsZS1hY2NlcHQtcmEuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZT0ibmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAiCgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lPSIkcHJlZml4LzAxLWRpc2FibGUtY29yZS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGU9Imtlcm5lbC5jb3JlX3BhdHRlcm4gPSB8L2Jpbi90cnVlCiAgICAiCiAgICB3cml0ZV9maWxlIGRpc2FibGVfY29yZV9maWxlbmFtZSBkaXNhYmxlX2NvcmVfZmlsZSB0cnVlCgogICAgc3lzY3RsIC0tc3lzdGVtCgogICAgbG9jYWwgLXJhIGVuYWJsZV9wb3J0cz0oCiAgICAgICAgIjQ0My90Y3AiCiAgICAgICAgIjQ0NC90Y3AiCiAgICAgICAgIjQ0NS90Y3AiCiAgICAgICAgIjIyMjIvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgogICAgCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKICAgIGF6IGFjciBsb2dpbiAtLW5hbWUgIiQoc2VkIC1lICdzfC4qL3x8JyA8PDwiJEFDUlJFU09VUkNFSUQiKSIKCiAgICBNRE1JTUFHRT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99IgogICAgZG9ja2VyIHB1bGwgIiRNRE1JTUFHRSIKICAgIGRvY2tlciBwdWxsICIkUlBJTUFHRSIKICAgIGRvY2tlciBwdWxsICIkRkxVRU5UQklUSU1BR0UiCgogICAgYXogbG9nb3V0Cn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMgICBmbHVlbnRiaXQKIyAgIG1kbQojICAgbWRzZAojICAgYXJwLXJwCiMgICBhcm8tZGJ0b2tlbgojICAgYXJvLW1vbml0b3IKIyAgIGFyby1wb3J0YWwKY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcygpIHsKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRtCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKCiAgICBta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KICAgIG1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lPScvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZicKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBhc3luY3FvcyBhc3luY3FvcyB0cnVlCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGFzeW5jcW9zCglSZW1vdmUgQ0xJRU5UX1BSSU5DSVBBTF9OQU1FCglSZW1vdmUgRklMRQoJUmVtb3ZlIENPTVBPTkVOVAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGlmeGF1ZGl0IGlmeGF1ZGl0IGZhbHNlCgpbT1VUUFVUXQoJTmFtZSBmb3J3YXJkCglNYXRjaCAqCglQb3J0IDI5MjMwIgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWUgZmx1ZW50Yml0X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0JwogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlPSJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiCgogICAgd3JpdGVfZmlsZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIG1rZGlyIC9ldGMvYXJvLXJwCiAgICBiYXNlNjQgLWQgPDw8IiRBRE1JTkFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYWRtaW4tY2EtYnVuZGxlLnBlbQogICAgaWYgW1sgLW4gIiRBUk1BUElDQUJVTkRMRSIgXV07IHRoZW4KICAgIGJhc2U2NCAtZCA8PDwiJEFSTUFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYXJtLWNhLWJ1bmRsZS5wZW0KICAgIGZpCiAgICBjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCiAgICAjIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAogICAgIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5LgogICAgbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCiAgICBjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xICJ7Kn0iID4vZGV2L251bGwKICAgIGNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIgogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZT0iewogICAgXCJOaWNlXCI6IDE5LAogICAgXCJUaW1lb3V0XCI6IDEwODAwLAogICAgXCJDbGllbnRJZFwiOiBcIlwiLAogICAgXCJUZW5hbnRJZFwiOiAkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQsCiAgICBcIlF1YWx5c1N0b3JlQmFzZVVybFwiOiAkQVpVUkVTRUNQQUNLUVVBTFlTVVJMLAogICAgXCJQcm9jZXNzVGltZW91dFwiOiAzMDAsCiAgICBcIkNvbW1hbmREZWxheVwiOiAwCiAgfSIKCiAgICB3cml0ZV9maWxlIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lIG5vZGVzY2FuX2FnZW50X2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGVuYW1lPSIvZXRjL3N5c2NvbmZpZy9tZG0iCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGU9Ik1ETUZST05URU5EVVJMPSckTURNRlJPTlRFTkRVUkwnCk1ETUlNQUdFPSckTURNSU1BR0UnCk1ETVNPVVJDRUVOVklST05NRU5UPSckTE9DQVRJT04nCk1ETVNPVVJDRVJPTEU9cnAKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwicnAtXCR7Q09NUE9ORU5UfVwiCk5FV19DRVJUX0ZJTEU9XCJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbVwiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBcCiAgICBzZWNyZXQgXAogICAgZG93bmxvYWQgXAogICAgLS1maWxlIFwiXCRORVdfQ0VSVF9GSUxFXCIgXAogICAgLS1pZCBcImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FXCIgXAogICAgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kc2RcIiBdXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkTkVXX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgY3VycmVudF9jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkQ1VSUkVOVF9DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGlmIFtbICEgLXogXCRuZXdfY2VydF9zbiBdXSAmJiBbWyBcJG5ld19jZXJ0X3NuICE9IFwiXCRjdXJyZW50X2NlcnRfc25cIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkiCgogICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGUgdHJ1ZQoKICAgIGNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIKCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KCiAgICBsb2NhbCAtciBNRFNEQ0VSVElGSUNBVEVTQU49IiQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGU9IltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHM9J3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgc3lzdGVtY3RsIGVuYWJsZSAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBlbmFibGUgJHdhdGNoX21kbV9jcmVkcyIKICAgIHN5c3RlbWN0bCBzdGFydCAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBzdGFydCAkd2F0Y2hfbWRtX2NyZWRzIgp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEdBVEVXQVlTRVJWSUNFUFJJTkNJUEFMSUQnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1EQlRva2VuClJQSU1BR0U9JyRSUElNQUdFJyIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbApjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCcKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGU9IkFaVVJFX1BPUlRBTF9BQ0NFU1NfR1JPVVBfSURTPSckUE9SVEFMQUNDRVNTR1JPVVBJRFMnCkFaVVJFX1BPUlRBTF9DTElFTlRfSUQ9JyRQT1JUQUxDTElFTlRJRCcKQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUz0nJFBPUlRBTEVMRVZBVEVER1JPVVBJRFMnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1Qb3J0YWwKUE9SVEFMX0hPU1ROQU1FPSckTE9DQVRJT04uYWRtaW4uJFJQUEFSRU5URE9NQUlOTkFNRScKUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZHNkCmNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIG1kc2Rfc2VydmljZV9kaXI9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRzZC5zZXJ2aWNlLmQiCiAgICBta2RpciAiJG1kc2Rfc2VydmljZV9kaXIiCgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGVuYW1lPSIkbWRzZF9zZXJ2aWNlX2Rpci9vdmVycmlkZS5jb25mIgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWUgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L21kc2QiCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZT0iTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPVwiLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYXCIKCmV4cG9ydCBNT05JVE9SSU5HX0dDU19FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FDQ09VTlQ9JyRSUE1EU0RBQ0NPVU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfUkVHSU9OPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0CmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEPSckTURTRENFUlRJRklDQVRFU0FOJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfTkFNRVNQQUNFPSckUlBNRFNETkFNRVNQQUNFJwpleHBvcnQgTU9OSVRPUklOR19DT05GSUdfVkVSU0lPTj0nJFJQTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9cnAKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb25WTVNTLnNoCiAgICBzb3VyY2UgY29tbW9uVk1TUy5zaAoKICAgIGNyZWF0ZV9yZXF1aXJlZF9kaXJzCiAgICBjb25maWd1cmVfc3NoZAogICAgY29uZmlndXJlX3JwbV9yZXBvcyByZXRyeV93YWl0X3RpbWUKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBkbmZfdXBkYXRlX3BrZ3MgZXhjbHVkZV9wa2dzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSBycG1fa2V5cz0oCiAgICAgICAgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKICAgICAgICBodHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20va2V5cy9taWNyb3NvZnQuYXNjCiAgICApCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSBpbnN0YWxsX3BrZ3M9KAogICAgICAgIGNsYW1hdgogICAgICAgIGF6c2VjLWNsYW1hdgogICAgICAgIGF6c2VjLW1vbml0b3IKICAgICAgICBhenVyZS1jbGkKICAgICAgICBhenVyZS1tZHNkCiAgICAgICAgYXp1cmUtc2VjdXJpdHkKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICAgICAgb3BlbnNzbC1wZXJsCiAgICAgICAgIyBoYWNrIC0gd2UgYXJlIGluc3RhbGxpbmcgcHl0aG9uMyBvbiBob3N0cyBkdWUgdG8gYW4gaXNzdWUgd2l0aCBBenVyZSBMaW51eCBFeHRlbnNpb25zIGh0dHBzOi8vZ2l0aHViLmNvbS9BenVyZS9henVyZS1saW51eC1leHRlbnNpb25zL3B1bGwvMTUwNQogICAgICAgIHB5dGhvbjMKICAgICkKCiAgICBkbmZfaW5zdGFsbF9wa2dzIGluc3RhbGxfcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGNvbmZpZ3VyZV9kbmZfY3Jvbl9qb2IKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKCiAgICAjIEtleSBkaWN0YXRlcyB0aGUgZmlsZW5hbWUgd3JpdHRlbiBpbiAvZXRjL2xvZ3JvdGF0ZS5kCiAgICAjIFByZXNlbnQgZm9yIGZ1dHVyZSBkcm9waW4gZmlsZXMsIGFsc28gaXMgcmVxdWlyZWQgZm9yIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGxvY2FsIC1yQSBsb2dyb3RhdGVfZHJvcGlucz0oKQogICAgY29uZmlndXJlX2xvZ3JvdGF0ZSBsb2dyb3RhdGVfZHJvcGlucwogICAgY29uZmlndXJlX3NlbGludXgKCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiNDQzL3RjcCIKICAgICAgICAiNDQ0L3RjcCIKICAgICAgICAiNDQ1L3RjcCIKICAgICAgICAiMjIyMi90Y3AiCiAgICApCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBlbmFibGVfcG9ydHMKCiAgICBsb2NhbCAtciBtZG1pbWFnZT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99IgogICAgbG9jYWwgLXIgcnBpbWFnZT0iJFJQSU1BR0UiCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfaW1hZ2U9IiRGTFVFTlRCSVRJTUFHRSIKICAgIGxvY2FsIC1yYSBpbWFnZXM9KAogICAgICAgICIkbWRtaW1hZ2UiCiAgICAgICAgIiRycGltYWdlIgogICAgICAgICIkZmx1ZW50Yml0X2ltYWdlIgogICAgKQoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9IiIKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXMgcmVnaXN0cnlfY29uZmlnX2ZpbGUKCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfY29uZl9maWxlPSJbSU5QVVRdCk5hbWUgc3lzdGVtZApUYWcgam91cm5hbGQKU3lzdGVtZF9GaWx0ZXIgX0NPTU09YXJvCkRCIC92YXIvbGliL2ZsdWVudC9qb3VybmFsZGIKCltGSUxURVJdCglOYW1lIG1vZGlmeQoJTWF0Y2ggam91cm5hbGQKCVJlbW92ZV93aWxkY2FyZCBfCglSZW1vdmUgVElNRVNUQU1QCgpbRklMVEVSXQoJTmFtZSByZXdyaXRlX3RhZwoJTWF0Y2ggam91cm5hbGQKCVJ1bGUgJExPR0tJTkQgYXN5bmNxb3MgYXN5bmNxb3MgdHJ1ZQoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBhc3luY3FvcwoJUmVtb3ZlIENMSUVOVF9QUklOQ0lQQUxfTkFNRQoJUmVtb3ZlIEZJTEUKCVJlbW92ZSBDT01QT05FTlQKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBpZnhhdWRpdCBpZnhhdWRpdCBmYWxzZQoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMCIKCiAgICBjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQgZmx1ZW50Yml0X2NvbmZfZmlsZSBmbHVlbnRiaXRfaW1hZ2UKICAgIGxvY2FsIC1yIG1vbml0b3Jfcm9sZT0icnAiCiAgICBjb25maWd1cmVfc2VydmljZV9tZG0gbW9uaXRvcl9yb2xlIG1kbWltYWdlCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkIG1vbml0b3Jfcm9sZQogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3JwCgogICAgY29uZmlndXJlX3NlcnZpY2VfZGJ0b2tlbiBycGltYWdlCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvciBycGltYWdlCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsIHJwaW1hZ2UKICAgIGxvY2FsIC1yIG1kc2RfcnBfdmVyc2lvbj0iJFJQTURTRENPTkZJR1ZFUlNJT04iCiAgICBjb25maWd1cmVfc2VydmljZV9tZHNkIG1vbml0b3Jfcm9sZSBtZHNkX3JwX3ZlcnNpb24KCiAgICBjb25maWd1cmVfY2VydHMgbW9uaXRvcl9yb2xlCgogICAgbG9jYWwgLXJhIGFyb19zZXJ2aWNlcz0oCiAgICAgICAgImFyby1kYnRva2VuIgogICAgICAgICJhcm8tbW9uaXRvciIKICAgICAgICAiYXJvLXBvcnRhbCIKICAgICAgICAiYXJvLXJwIgogICAgICAgICJhdW9tcyIKICAgICAgICAiYXpzZWNkIgogICAgICAgICJhenNlY21vbmQiCiAgICAgICAgIm1kc2QiCiAgICAgICAgIm1kbSIKICAgICAgICAiY2hyb255ZCIKICAgICAgICAiZmx1ZW50Yml0IgogICAgICAgICJkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyIgogICAgICAgICJkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIiCiAgICApCgogICAgZW5hYmxlX3NlcnZpY2VzIGFyb19zZXJ2aWNlcwoKICAgIHJlYm9vdF92bQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvY2FsIC1uIGltYWdlPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJGltYWdlJyIKCiAgICB3cml0ZV9maWxlIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX21vbml0b3Jfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tbW9uaXRvci5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX21vbml0b3Jfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tbW9uaXRvcgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0ZQX0NMSUVOVF9JRCBcCiAgLWUgRE9NQUlOX05BTUUgXAogIC1lIENMVVNURVJfTURTRF9BQ0NPVU5UIFwKICAtZSBDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT04gXAogIC1lIEdBVEVXQVlfRE9NQUlOUyBcCiAgLWUgR0FURVdBWV9SRVNPVVJDRUdST1VQIFwKICAtZSBNRFNEX0VOVklST05NRU5UIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01ETV9BQ0NPVU5UIFwKICAtZSBDTFVTVEVSX01ETV9OQU1FU1BBQ0UgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMi41ZyBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRpbWFnZSBcCiAgbW9uaXRvcgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZW5hbWUgYXJvX21vbml0b3Jfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsCmNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19wb3J0YWwoKSB7CiAgICBsb2NhbCAtbiBpbWFnZT0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsJwogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFM9JyRQT1JUQUxBQ0NFU1NHUk9VUElEUycKQVpVUkVfUE9SVEFMX0NMSUVOVF9JRD0nJFBPUlRBTENMSUVOVElEJwpBWlVSRV9QT1JUQUxfRUxFVkFURURfR1JPVVBfSURTPSckUE9SVEFMRUxFVkFURURHUk9VUElEUycKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVBvcnRhbApQT1JUQUxfSE9TVE5BTUU9JyRMT0NBVElPTi5hZG1pbi4kUlBQQVJFTlRET01BSU5OQU1FJwpSUElNQUdFPSckaW1hZ2UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRpbWFnZSBcCiAgcG9ydGFsClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19wb3J0YWxfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9kYnRva2VuKCkgewogICAgbG9jYWwgLW4gaW1hZ2U9IiQxIgogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBjb25mX2ZpbGU9IkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpBWlVSRV9HQVRFV0FZX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckR0FURVdBWVNFUlZJQ0VQUklOQ0lQQUxJRCcKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPURCVG9rZW4KUlBJTUFHRT0nJGltYWdlJyIKCiAgICBsb2NhbCAtciBjb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKCiAgICB3cml0ZV9maWxlIGNvbmZfZmlsZW5hbWUgY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBzZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRCBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDQ0NTo4NDQ1IFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJGltYWdlIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICBsb2NhbCAtciBzZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1kYnRva2VuLnNlcnZpY2UnCiAgICB3cml0ZV9maWxlIHNlcnZpY2VfZmlsZW5hbWUgc2VydmljZV9maWxlIHRydWUKfQoKCmV4cG9ydCBBWlVSRV9DTE9VRF9OQU1FPSIke0FaVVJFQ0xPVUROQU1FOj8iRmFpbGVkIHRvIGNhcnJ5IG92ZXIgdmFyaWFibGVzIn0iCgptYWluICIkQCIK')))]" } } } diff --git a/pkg/deploy/generator/scripts/commonVMSS.sh b/pkg/deploy/generator/scripts/commonVMSS.sh new file mode 100644 index 00000000000..6f54ced7354 --- /dev/null +++ b/pkg/deploy/generator/scripts/commonVMSS.sh @@ -0,0 +1,726 @@ +#!/bin/bash +# This file is intended to be sourced by bootstrapping scripts for commonly used functions + +# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks +retry() { + local -n cmd_retry="$1" + local -n wait_time="$2" + + for attempt in {1..5}; do + log "attempt #${attempt} - ${FUNCNAME[2]}" + ${cmd_retry[@]} & + + wait $! && break + if [[ ${attempt} -lt 5 ]]; then + sleep "$wait_time" + else + abort "attempt #${attempt} - Failed to update packages" + fi + done +} + +# dnf_install_pkgs +dnf_install_pkgs() { + local -n pkgs="$1" + log "starting" + + local -ra cmd=( + dnf + -y + install + ${pkgs[@]} + ) + + log "Attempting to install packages: ${pkgs[*]}" + retry cmd "$2" +} + +# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work +configure_sshd() { + log "starting" + local sshd_config="/etc/ssh/sshd_config" + + log "Editing $sshd_config to allow password authentication" + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' "$sshd_config" + + systemctl reload sshd.service || abort "sshd failed to reload" +} + +# dnf_update_pkgs +dnf_update_pkgs() { + local -n excludes="$1" + log "starting" + + local -ra cmd=( + dnf + -y + ${excludes[@]} + update + --allowerasing + ) + + log "Updating all packages excluding ${excludes[*]}" + retry cmd "$2" +} + +# rpm_import_keys +rpm_import_keys() { + local -n keys="$1" + log "starting" + + + # shellcheck disable=SC2068 + for key in ${keys[@]}; do + if [ ${#keys[@]} -eq 0 ]; then + break + fi + local -a cmd=( + rpm + --import + -v + "$key" + ) + + log "attempt #$attempt - importing rpm repository key $key" + retry cmd "$2" && unset key + done +} + +# configure_selinux +configure_selinux() { + log "starting" + + local -r relabel="${1:-false}" + + already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" + chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent + + if "$relabel"; then + restorecon -RF /var/log/* || log "$already_defined_ignore_error" + fi +} + +# configure_firewalld_rules +configure_firewalld_rules() { + local -n ports="$1" + log "starting" + + # https://access.redhat.com/security/cve/cve-2020-13401 + local -r prefix="/etc/sysctl.d" + local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" + local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" + + write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true + + local -r disable_core_filename="$prefix/01-disable-core.conf" + local -r disable_core_file="kernel.core_pattern = |/bin/true + " + write_file disable_core_filename disable_core_file true + + sysctl --system + + log "Enabling ports ${ports[*]} on default firewalld zone" + # shellcheck disable=SC2068 + for port in ${ports[@]}; do + log "Enabling port $port now" + firewall-cmd "--add-port=$port" + done + + firewall-cmd --runtime-to-permanent +} + +# configure_logrotate clobbers /etc/logrotate.conf +# args: +# 1) dropin_files - associative array. Key name dictates filenames written to /etc/logrotate.d. +# If an empty array is provided, no files will be written +configure_logrotate() { + local -n dropin_files="$1" + log "starting" + + local -r logrotate_conf_filename='/etc/logrotate.conf' + local -r logrotate_conf_file='# see "man logrotate" for details +# rotate log files weekly +weekly + +# keep 2 weeks worth of backlogs +rotate 2 + +# create new (empty) log files after rotating old ones +create + +# use date as a suffix of the rotated file +dateext + +# uncomment this if you want your log files compressed +compress + +# RPM packages drop log rotation information into this directory +include /etc/logrotate.d + +# no packages own wtmp and btmp -- we will rotate them here +/var/log/wtmp { + monthly + create 0664 root utmp + minsize 1M + rotate 1 +} + +/var/log/btmp { + missingok + monthly + create 0600 root utmp + rotate 1 +}' + + write_file logrotate_conf_filename logrotate_conf_file true + + local -r logrotate_d="/etc/logrotate.d" + log "Writing logrotate files to $logrotate_d" + for dropin_name in "${!dropin_files[@]}"; do + local -r dropin_filename="$logrotate_d/$dropin_name" + local -r dropin_file="${dropin_files["$dropin_name"]}" + write_file dropin_filename dropin_file true + done +} + +# pull_container_images +pull_container_images() { + local -n pull_images="$1" + local -n registry_conf="${2:-empty}" + local -r az_login="${3:-true}" + log "starting" + + # The managed identity that the VM runs as only has a single roleassignment. + # This role assignment is ACRPull which is not necessarily present in the + # subscription we're deploying into. If the identity does not have any + # role assignments scoped on the subscription we're deploying into, it will + # not show on az login -i, which is why the below line is commented. + # az account set -s "$SUBSCRIPTIONID" + if $az_login; then + az login -i --allow-no-subscriptions + fi + + # Suppress emulation output for podman instead of docker for az acr compatability + mkdir -p /etc/containers/ + mkdir -p /root/.docker + touch /etc/containers/nodocker + + # This name is used in the case that az acr login searches for this in it's environment + local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + + if [[ -n $registry_conf ]]; then + write_file REGISTRY_AUTH_FILE registry_conf true + fi + + log "logging into prod acr" + if $az_login; then + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + fi + + # shellcheck disable=SC2068 + for i in ${pull_images[@]}; do + log "Pulling image $i now" + podman pull "$i" + done + + if $az_login; then + az logout + fi +} + +# enable_services enables all services required for aro rp +enable_services() { + local -n services="$1" + log "starting" + + systemctl daemon-reload + + log "enabling services ${services[*]}" + # shellcheck disable=SC2068 + for service in ${services[@]}; do + log "Enabling $service now" + systemctl enable "$service" + done +} + +# write_file +# Args +# 1) filename - string +# 2) file_contents - string +# 3) clobber - boolean; optional - defaults to false +write_file() { + local -n filename="$1" + local -n file_contents="$2" + local -r clobber="${3:-false}" + + if $clobber; then + log "Overwriting file $filename" + echo "$file_contents" > "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} + +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" + + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} + +# configure_rpm_repos +# New repositories should be added in their own functions, and called here +# args: +# 1) retry_wait_time - nameref +configure_rpm_repos() { + log "starting" + + configure_rhui_repo "$1" + create_azure_rpm_repos +} + +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "starting" + + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] +name=azure-cli +baseurl=https://packages.microsoft.com/yumrepos/azure-cli +enabled=yes +gpgcheck=yes + +[azurecore] +name=azurecore +baseurl=https://packages.microsoft.com/yumrepos/azurecore +enabled=yes +gpgcheck=no' + + write_file azure_repo_filename azure_repo_file true +} + +# configure_rhui_repo enables all rhui-microsoft-azure* repos +# args: +# 1) retry_wait_time - nameref +configure_rhui_repo() { + log "starting" + + local -ra cmd=( + dnf + update + -y + --disablerepo='*' + --enablerepo='rhui-microsoft-azure*' + ) + + log "running RHUI package updates" + retry cmd "$1" +} + +configure_dnf_cron_job() { + log "Starting" + local -r cron_weekly_dnf_update_filename='/etc/cron.weekly/dnfupdate' + local -r cron_weekly_dnf_update_file="#!/bin/bash +dnf update -y" + + write_file cron_weekly_dnf_update_filename cron_weekly_dnf_update_file true + chmod +x "$cron_weekly_dnf_update_filename" +} + +# configure_disk_partitions +configure_disk_partitions() { + log "starting" + log "extending partition table" + + # Linux block devices are inconsistently named + # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here + physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physical_disk" 2 + + log "extending filesystems" + log "extending root lvm" + lvextend -l +20%FREE /dev/rootvg/rootlv + log "growing root filesystem" + xfs_growfs / + + log "extending var lvm" + lvextend -l +100%FREE /dev/rootvg/varlv + log "growing var filesystem" + xfs_growfs /var +} + +# configure_certs +configure_certs() { + local -n role="$1" + log "starting" + log "Configuring certificates for $role" + + if [ "$role" == "devproxy" ]; then + local -r proxy_certs_basedir="/etc/proxy" + mkdir -p "$proxy_certs_basedir" + base64 -d <<<"$PROXYCERT" > "$proxy_certs_basedir/proxy.crt" + base64 -d <<<"$PROXYKEY" > "$proxy_certs_basedir/proxy.key" + base64 -d <<<"$PROXYCLIENTCERT" > "$proxy_certs_basedir/proxy-client.crt" + chown -R 1000:1000 /etc/proxy + chmod 0600 "$proxy_certs_basedir/proxy.key" + return 0 + fi + + if [ "$role" == "rp" ]; then + local -r rp_certs_basedir="/etc/aro-rp" + mkdir -p + base64 -d <<<"$ADMINAPICABUNDLE" > "$rp_certs_basedir/admin-ca-bundle.pem" + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" > "$rp_certs_basedir/arm-ca-bundle.pem" + fi + chown -R 1000:1000 "$rp_certs_basedir" + fi + + # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not + # to honour SSL_CERT_FILE any more, heaven only knows why. + local -r ssl_certs_basedir="/usr/lib/ssl/certs" + mkdir -p + csplit -f "$ssl_certs_basedir/cert-" -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null + c_rehash "$ssl_certs_basedir" + + # we leave clientId blank as long as only 1 managed identity assigned to vmss + # if we have more than 1, we will need to populate with clientId used for off-node scanning + local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" + local -r nodescan_agent_file="{ + \"Nice\": 19, + \"Timeout\": 10800, + \"ClientId\": \"\", + \"TenantId\": $AZURESECPACKVSATENANTID, + \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, + \"ProcessTimeout\": 300, + \"CommandDelay\": 0 + }" + + write_file nodescan_agent_filename nodescan_agent_file true +} + +# configure_service_mdm +configure_service_mdm() { + local -n role="$1" + local -n image="$2" + log "starting" + log "configuring mdm service" + + local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" + local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' +MDMIMAGE='$image' +MDMSOURCEENVIRONMENT='$LOCATION' +MDMSOURCEROLE='$role' +MDMSOURCEROLEINSTANCE=\"$(hostname)\"" + + write_file sysconfig_mdm_filename sysconfig_mdm_file true + + mkdir -p /var/etw + local -r mdm_service_filename="/etc/systemd/system/mdm.service" + local -r mdm_service_file="[Unit] +After=network-online.target +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/mdm +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --entrypoint /usr/sbin/MetricsExtension \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -m 2g \ + -v /etc/mdm.pem:/etc/mdm.pem \ + -v /var/etw:/var/etw:z \ + $image \ + -CertFile /etc/mdm.pem \ + -FrontEndUrl $MDMFRONTENDURL \ + -Logger Console \ + -LogLevel Warning \ + -PrivateKeyFile /etc/mdm.pem \ + -SourceEnvironment $MDMSOURCEENVIRONMENT \ + -SourceRole $MDMSOURCEROLE \ + -SourceRoleInstance $MDMSOURCEROLEINSTANCE +ExecStop=/usr/bin/docker stop %N +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file mdm_service_filename mdm_service_file true +} + +# configure_timers_mdm_mdsd +configure_timers_mdm_mdsd() { + local -n component="$1" + log "starting" + + for var in "mdsd" "mdm"; do + local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" + local download_creds_service_file="[Unit] +Description=Periodic $var credentials refresh + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/download-credentials.sh $var" + + write_file download_creds_service_filename download_creds_service_file true + + local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" + local download_creds_timer_file="[Unit] +Description=Periodic $var credentials refresh +After=network-online.target +Wants=network-online.target + +[Timer] +OnBootSec=0min +OnCalendar=0/12:00:00 +AccuracySec=5s + +[Install] +WantedBy=timers.target" + + write_file download_creds_timer_filename download_creds_timer_file true + done + + local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" + local -r download_creds_script_file="#!/bin/bash +set -eu + +COMPONENT=\$1 +echo \"Download \$COMPONENT credentials\" + +TEMP_DIR=\"\$(mktemp -d)\" +export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" + +echo \"Logging into Azure...\" +RETRIES=3 +while [[ \$RETRIES -gt 0 ]]; do + if az login -i --allow-no-subscriptions + then + echo \"az login successful\" + break + else + echo \"az login failed. Retrying...\" + let RETRIES-=1 + sleep 5 + fi +done + +trap \"cleanup\" EXIT + +cleanup() { + az logout + [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR + [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR +} + +if [[ \$COMPONENT = \"mdm\" ]]; then + CURRENT_CERT_FILE=\"/etc/mdm.pem\" +elif [[ \$COMPONENT = \"mdsd\" ]]; then + CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" +else + echo Invalid usage && exit 1 +fi + +SECRET_NAME=\"$component-\${COMPONENT}\" +NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" +for attempt in {1..5}; do + az keyvault \ + secret \ + download \ + --file \"\$NEW_CERT_FILE\" \ + --id \"https://$KEYVAULTPREFIX-$component.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ + && break + if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi +done + +if [ -f \$NEW_CERT_FILE ]; then + if [[ \$COMPONENT = \"mdsd\" ]]; then + chown syslog:syslog \$NEW_CERT_FILE + else + sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE + fi + + new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" + current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" + if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then + echo updating certificate for \$COMPONENT + chmod 0600 \$NEW_CERT_FILE + mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE + fi +else + echo Failed to refresh certificate for \$COMPONENT && exit 1 +fi" + + write_file download_creds_script_filename download_creds_script_file true + + chmod u+x /usr/local/bin/download-credentials.sh + + $download_creds_script_filename mdsd + $download_creds_script_filename mdm + + local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" + local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" + local -r watch_mdm_creds_service_file="[Unit] +Description=Watch for changes in mdm.pem and restarts the mdm service + +[Service] +Type=oneshot +ExecStart=/usr/bin/systemctl restart mdm.service + +[Install] +WantedBy=multi-user.target" + + write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true + + local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' + local -r watch_mdm_creds_path_file='[Path] +PathModified=/etc/mdm.pem + +[Install] +WantedBy=multi-user.target' + + write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true + + local -r watch_mdm_creds='watch-mdm-credentials.path' + systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" + systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" +} + +# configure_service_fluentbit +configure_service_fluentbit() { + local -n conf_file="$1" + local -n image="$2" + log "starting" + log "configuring fluentbit service" + + mkdir -p /etc/fluentbit/ + mkdir -p /var/lib/fluent + + local -r conf_filename='/etc/fluentbit/fluentbit.conf' + write_file conf_filename conf_file true + + local -r sysconfig_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_file="FLUENTBITIMAGE=$fluentbit_image" + + write_file sysconfig_filename sysconfig_file true + + local -r service_filename='/etc/systemd/system/fluentbit.service' + local -r service_file="[Unit] +After=network-online.target +Wants=network-online.target +StartLimitIntervalSec=0 + +[Service] +RestartSec=1s +EnvironmentFile=/etc/sysconfig/fluentbit +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --security-opt label=disable \ + --entrypoint /opt/td-agent-bit/bin/td-agent-bit \ + --net=host \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -v /etc/fluentbit/fluentbit.conf:/etc/fluentbit/fluentbit.conf \ + -v /var/lib/fluent:/var/lib/fluent:z \ + -v /var/log/journal:/var/log/journal:ro \ + -v /etc/machine-id:/etc/machine-id:ro \ + $image \ + -c /etc/fluentbit/fluentbit.conf + +ExecStop=/usr/bin/docker stop %N +Restart=always +RestartSec=5 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file service_filename service_file true +} + +# configure_service_mdsd +configure_service_mdsd() { + local -n monitoring_role="$1" + local -n monitor_config_version="$2" + log "starting" + + local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" + mkdir -p "$mdsd_service_dir" + + local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" + local -r mdsd_override_conf_file="[Unit] +After=network-online.target" + + write_file mdsd_override_conf_filename mdsd_override_conf_file true + + local -r default_mdsd_filename="/etc/default/mdsd" + local -r default_mdsd_file="MDSD_ROLE_PREFIX=/var/run/mdsd/default +MDSD_OPTIONS=\"-A -d -r \$MDSD_ROLE_PREFIX\" + +export MONITORING_GCS_ENVIRONMENT='$MDSDENVIRONMENT' +export MONITORING_GCS_ACCOUNT='$RPMDSDACCOUNT' +export MONITORING_GCS_REGION='$LOCATION' +export MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault +export MONITORING_GCS_AUTH_ID='$MDSDCERTIFICATESAN' +export MONITORING_GCS_NAMESPACE='$RPMDSDNAMESPACE' +export MONITORING_CONFIG_VERSION='$monitor_config_version' +export MONITORING_USE_GENEVA_CONFIG_SERVICE=true + +export MONITORING_TENANT='$LOCATION' +export MONITORING_ROLE='$monitoring_role' +export MONITORING_ROLE_INSTANCE=\"$(hostname)\" + +export MDSD_MSGPACK_SORT_COLUMNS=1\"" + + write_file default_mdsd_filename default_mdsd_file true +} + +# run_azsecd_config_scan +run_azsecd_config_scan() { + log "starting" + + local -ar configs=( + "baseline" + "clamav" + "software" + ) + + log "Scanning configuration files ${configs[*]}" + # shellcheck disable=SC2068 + for scan in ${configs[@]}; do + log "Scanning config file $scan now" + /usr/local/bin/azsecd config -s "$scan" -d P1D + done +} + +create_required_dirs() { + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + # Does not exist on devProxyVMSS + mkdir -p /var/opt/microsoft/linuxmonagent +} diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index 2b405881bce..23aab382c85 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -8,319 +8,69 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { - parse_run_options "$@" - - configure_and_install_dnf_pkgs_repos - - configure_firewalld_rules - pull_container_images - configure_system_services - reboot_vm -} - -usage() { - local -n options="$1" - log "$(basename "$0") [$options] - -p Configure rpm repositories, import required rpm keys, update & install packages with dnf - -f Configure firewalld default zone rules - -u Configure systemd unit files for ARO RP - -i Pull container images - - Note: steps will be executed in the order that flags are provided - " -} - -# parse_run_options takes all arguements passed to main and parses them -# allowing individual step(s) to be ran, rather than all steps -# -# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline -parse_run_options() { - # shellcheck disable=SC2206 - local -a options=(${1:-}) - if [ "${#options[@]}" -eq 0 ]; then - log "Running all steps" - return 0 - fi - - local OPTIND - local -r allowed_options="pfui" - while getopts ${allowed_options} options; do - case "${options}" in - p) - log "Running step configure_and_install_dnf_pkgs_repos" - configure_and_install_dnf_pkgs_repos - ;; - f) - log "Running configure_firewalld_rules" - configure_firewalld_rules - ;; - u) - log "Running pull_container_images & configure_system_services" - configure_system_services - ;; - i) - log "Running pull_container_images" - pull_container_images - ;; - *) - usage allowed_options - abort "Unkown option provided" - ;; - esac - done - - exit 0 -} - -# configure_and_install_dnf_pkgs_repos -configure_and_install_dnf_pkgs_repos() { - log "starting" - # transaction attempt retry time in seconds local -ri retry_wait_time=60 - configure_rhui_repo retry_wait_time + + # shellcheck source=commonVMSS.sh + source commonVMSS.sh + + create_required_dirs local -ar exclude_pkgs=( "-x WALinuxAgent" "-x WALinuxAgent-udev" ) - dnf_update_pkgs exclude_pkgs retry_wait_time - - local -ra repo_rpm_pkgs=( - https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - ) + dnf_update_pkgs pkgs_to_exclude retry_wait_time local -ra install_pkgs=( podman podman-docker ) - dnf_install_pkgs repo_rpm_pkgs retry_wait_time dnf_install_pkgs install_pkgs retry_wait_time - - local -r cron_weekly_dnf_update_filename='/etc/cron.weekly/dnfupdate' - local -r cron_weekly_dnf_update_file="#!/bin/bash -dnf update -y" - - write_file cron_weekly_dnf_update_filename cron_weekly_dnf_update_file true - chmod +x "$cron_weekly_dnf_update_filename" -} - -# configure_rhui_repo -configure_rhui_repo() { - log "starting" - - local -ra cmd=( - dnf - update - -y - --disablerepo='*' - --enablerepo='rhui-microsoft-azure*' - ) - - log "running RHUI package updates" - retry cmd "$1" -} - -# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks -retry() { - local -n cmd_retry="$1" - local -n wait_time="$2" - - for attempt in {1..5}; do - log "attempt #${attempt} - ${FUNCNAME[2]}" - ${cmd_retry[@]} & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done -} - -# dnf_update_pkgs -dnf_update_pkgs() { - local -n excludes="$1" - log "starting" - - local -ra cmd=( - dnf - -y - ${excludes[@]} - update - --allowerasing - ) - - log "Updating all packages" - retry cmd "$2" -} - -# dnf_install_pkgs -dnf_install_pkgs() { - local -n pkgs="$1" - log "starting" - - local -ra cmd=( - dnf - -y - install - ${pkgs[@]} - ) - - log "Attempting to install packages: ${pkgs[*]}" - retry cmd "$2" -} - -# configure_logrotate clobbers /etc/logrotate.conf -configure_logrotate() { - log "starting" - - local -r logrotate_conf_filename='/etc/logrotate.conf' - local -r logrotate_conf_file='# see "man logrotate" for details -# rotate log files weekly -weekly - -# keep 2 weeks worth of backlogs -rotate 2 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we will rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} - -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -}' - - write_file logrotate_conf_filename logrotate_conf_file true -} - -# configure_firewalld_rules -configure_firewalld_rules() { - log "starting" - - # https://access.redhat.com/security/cve/cve-2020-13401 - local -r prefix="/etc/sysctl.d" - local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" - local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" - - write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true - - local -r disable_core_filename="$prefix/01-disable-core.conf" - local -r disable_core_file="kernel.core_pattern = |/bin/true - " - write_file disable_core_filename disable_core_file true - - sysctl --system + configure_dnf_cron_job local -ra enable_ports=( "443/tcp" ) - log "Enabling ports ${enable_ports[*]} on default firewalld zone" - # shellcheck disable=SC2068 - for port in ${enable_ports[@]}; do - log "Enabling port $port now" - firewall-cmd "--add-port=$port" - done - - firewall-cmd --runtime-to-permanent -} - -# pull_container_images -pull_container_images() { - log "starting" - - # The managed identity that the VM runs as only has a single roleassignment. - # This role assignment is ACRPull which is not necessarily present in the - # subscription we're deploying into. If the identity does not have any - # role assignments scoped on the subscription we're deploying into, it will - # not show on az login -i, which is why the below line is commented. - # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions + configure_firewalld_rules enable_ports - # Suppress emulation output for podman instead of docker for az acr compatability - mkdir -p /etc/containers/ - mkdir -p /root/.docker - touch /etc/containers/nodocker - - # This name is used in the case that az acr login searches for this in it's environment - local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + local -ra proxy_images=("$PROXYIMAGE") local -r registry_config_file="{ - "auths": { - \"${PROXYIMAGE%%/*}\": { - \"auth\": \"$PROXYIMAGEAUTH\" - } - }" - - write_file REGISTRY_AUTH_FILE registry_config_file true + \"auths\": { + \"${proxy_images[0]%%/*}\": { + \"auth\": \"$PROXYIMAGEAUTH\" + } + } +}" - log "logging into prod acr" + pull_container_images proxy_image registry_config_file false + configure_devproxy_services proxy_images - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + local -r vmss_role="devproxy" + configure_certs vmss_role - docker pull "$PROXYIMAGE" + local -ra proxy_services=( + proxy + ) - az logout + enable_services proxy_services + reboot_vm } # configure_system_services creates, configures, and enables the following systemd services and timers # services # proxy -configure_system_services() { - configure_service_proxy -} - -# enable_aro_services enables all services required for aro rp -enable_aro_services() { - log "starting" - - local -ra aro_services=( - proxy - ) - log "enabling aro services ${aro_services[*]}" - # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do - log "Enabling $service now" - systemctl enable "$service.service" - done -} - -# configure_certs -configure_certs() { - log "starting" - - base64 -d <<<"$PROXYCERT" >/etc/proxy/proxy.crt - base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key - base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt - chown -R 1000:1000 /etc/proxy - chmod 0600 /etc/proxy/proxy.key +configure_devproxy_services() { + configure_service_proxy "$1" } configure_service_proxy() { + local -n proxy_image="$1" local -r sysconfig_proxy_filename='/etc/sysconfig/proxy' - local -r sysconfig_proxy_file="PROXY_IMAGE='$PROXYIMAGE'" + local -r sysconfig_proxy_file="PROXY_IMAGE='$proxy_image'" write_file sysconfig_proxy_filename sysconfig_proxy_file true @@ -332,7 +82,7 @@ Wants=network-online.target [Service] EnvironmentFile=/etc/sysconfig/proxy ExecStartPre=-/usr/bin/docker rm -f %n -ExecStart=/usr/bin/docker run --rm --name %n -p 443:8443 -v /etc/proxy:/secrets $PROXY_IMAGE +ExecStart=/usr/bin/docker run --rm --name %n -p 443:8443 -v /etc/proxy:/secrets $proxy_image ExecStop=/usr/bin/docker stop %n Restart=always RestartSec=1 @@ -341,9 +91,11 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" + write_file proxy_service_filename proxy_service_file true + local -r cron_weekly_pull_image_filename='/etc/cron.weekly/pull-image' local -r cron_weekly_pull_image_file="#!/bin/bash -docker pull $PROXYIMAGE +docker pull $proxy_image systemctl restart proxy.service" write_file cron_weekly_pull_image_filename cron_weekly_pull_image_file true @@ -353,52 +105,10 @@ systemctl restart proxy.service" local -r cron_daily_restart_proxy_file="#!/bin/bash systemctl restart proxy.service" - write_file cron_daily_restart_proxy_filename cron_daily_restart_proxy_file + write_file cron_daily_restart_proxy_filename cron_daily_restart_proxy_file true chmod +x "$cron_daily_restart_proxy_filename" } -# write_file -# Args -# 1) filename - string -# 2) file_contents - string -# 3) clobber - boolean; optional - defaults to false -write_file() { - local -n filename="$1" - local -n file_contents="$2" - local -r clobber="${3:-false}" - - if $clobber; then - log "Overwriting file $filename" - echo "$file_contents" > "$filename" - else - log "Appending to $filename" - echo "$file_contents" >> "$filename" - fi -} - -# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots -reboot_vm() { - log "starting" - - configure_selinux "true" - (sleep 30 && log "rebooting vm now"; reboot) & -} - -# log is a wrapper for echo that includes the function name -log() { - local -r msg="${1:-"log message is empty"}" - local -r stack_level="${2:-1}" - echo "${FUNCNAME[${stack_level}]}: ${msg}" -} - -# abort is a wrapper for log that exits with an error code -abort() { - local -ri origin_stacklevel=2 - log "${1}" "$origin_stacklevel" - log "Exiting" - exit 1 -} - export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 64b4232309f..e24cd081142 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -8,124 +8,22 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { - local -r gateway_logdir='/var/log/aro-gateway' - parse_run_options "$@" gateway_logdir + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + # shellcheck source=commonVMSS.sh + source commonVMSS.sh + create_required_dirs configure_sshd - configure_and_install_dnf_pkgs_repos - configure_disk_partitions - configure_logrotate gateway_logdir - configure_selinux - - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - - configure_firewalld_rules - pull_container_images - configure_system_services gateway_logdir - reboot_vm -} - -usage() { - local -n options="$1" - log "$(basename "$0") [$options] - -d Configure Disk Partitions - -p Configure rpm repositories, import required rpm keys, update & install packages with dnf - -l Configure logrotate.conf - -s Make selinux modifications required for ARO RP - -r Configure sshd - Allow password authenticaiton - -f Configure firewalld default zone rules - -u Configure systemd unit files for ARO RP - -i Pull container images - - Note: steps will be executed in the order that flags are provided - " -} - -# parse_run_options takes all arguements passed to main and parses them -# allowing individual step(s) to be ran, rather than all steps -# -# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline -parse_run_options() { - # shellcheck disable=SC2206 - local -a options=(${1:-}) - if [ "${#options[@]}" -eq 0 ]; then - log "Running all steps" - return 0 - fi - - local OPTIND - local -r allowed_options="dplsrfui" - while getopts ${allowed_options} options; do - case "${options}" in - d) - log "Running step configure_disk_partitions" - configure_disk_partitions - ;; - p) - log "Running step configure_and_install_dnf_pkgs_repos" - configure_and_install_dnf_pkgs_repos - ;; - l) - log "Running configure_logrotate" - configure_logrotate "$2" - ;; - s) - log "Running configure_selinux" - configure_selinux - ;; - r) - log "Running configure_sshd" - configure_sshd - ;; - f) - log "Running configure_firewalld_rules" - configure_firewalld_rules - ;; - u) - log "Running pull_container_images & configure_system_services" - configure_system_services "$2" - ;; - i) - log "Running pull_container_images" - pull_container_images - ;; - *) - usage allowed_options - abort "Unkown option provided" - ;; - esac - done - - exit 0 -} - -# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work -configure_sshd() { - log "starting" - log "setting ssh password authentication" - sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config - - systemctl reload sshd.service - systemctl is-active --quiet sshd || abort "sshd failed to reload" -} - -# configure_and_install_dnf_pkgs_repos -configure_and_install_dnf_pkgs_repos() { - log "starting" - - # transaction attempt retry time in seconds - local -ri retry_wait_time=60 - configure_rhui_repo retry_wait_time - create_azure_rpm_repos retry_wait_time + configure_rpm_repos retry_wait_time local -ar exclude_pkgs=( "-x WALinuxAgent" "-x WALinuxAgent-udev" ) - dnf_update_pkgs exclude_pkgs retry_wait_time + dnf_update_pkgs pkgs_to_exclude retry_wait_time local -ra rpm_keys=( https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 @@ -138,6 +36,9 @@ configure_and_install_dnf_pkgs_repos() { https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm ) + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + configure_dnf_cron_job + local -ra install_pkgs=( clamav azsec-clamav @@ -152,163 +53,12 @@ configure_and_install_dnf_pkgs_repos() { python3 ) - dnf_install_pkgs repo_rpm_pkgs retry_wait_time dnf_install_pkgs install_pkgs retry_wait_time -} - -# configure_rhui_repo -configure_rhui_repo() { - log "starting" - - local -ra cmd=( - dnf - update - -y - --disablerepo='*' - --enablerepo='rhui-microsoft-azure*' - ) - - log "running RHUI package updates" - retry cmd "$1" -} - -# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks -retry() { - local -n cmd_retry="$1" - local -n wait_time="$2" - - for attempt in {1..5}; do - log "attempt #${attempt} - ${FUNCNAME[2]}" - ${cmd_retry[@]} & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done -} - -# dnf_update_pkgs -dnf_update_pkgs() { - local -n excludes="$1" - log "starting" - - local -ra cmd=( - dnf - -y - ${excludes[@]} - update - --allowerasing - ) - - log "Updating all packages" - retry cmd "$2" -} - -# dnf_install_pkgs -dnf_install_pkgs() { - local -n pkgs="$1" - log "starting" - - local -ra cmd=( - dnf - -y - install - ${pkgs[@]} - ) - - log "Attempting to install packages: ${pkgs[*]}" - retry cmd "$2" -} - -# rpm_import_keys -rpm_import_keys() { - local -n keys="$1" - log "starting" - - - # shellcheck disable=SC2068 - for key in ${keys[@]}; do - if [ ${#keys[@]} -eq 0 ]; then - break - fi - local -a cmd=( - rpm - --import - -v - "$key" - ) - - log "attempt #$attempt - importing rpm repository key $key" - retry cmd "$2" && unset key - done -} - -# configure_disk_partitions -configure_disk_partitions() { - log "starting" - log "extending partition table" - - # Linux block devices are inconsistently named - # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here - physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" - growpart "$physical_disk" 2 - - log "extending filesystems" - log "extending root lvm" - lvextend -l +20%FREE /dev/rootvg/rootlv - log "growing root filesystem" - xfs_growfs / - - log "extending var lvm" - lvextend -l +100%FREE /dev/rootvg/varlv - log "growing var filesystem" - xfs_growfs /var -} - -# configure_logrotate clobbers /etc/logrotate.conf -configure_logrotate() { - local -n log_dir="$1" - log "starting" - - local -r logrotate_conf_filename='/etc/logrotate.conf' - local -r logrotate_conf_file="# see 'man logrotate' for details -# rotate log files weekly -weekly - -# keep 2 weeks worth of backlogs -rotate 2 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we will rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -} + configure_disk_partitions -# Maximum log directory size is 100G with this configuration + local -r gateway_logdir='/var/log/aro-gateway' + local -r gateway_log_file="# Maximum log directory size is 100G with this configuration # Setting limit to 100G to allow space for other logging services # copytruncate is a critical option used to prevent logs from being shipped twice ${log_dir} { @@ -320,157 +70,32 @@ ${log_dir} { compress }" - write_file logrotate_conf_filename logrotate_conf_file true -} - -# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file -create_azure_rpm_repos() { - log "starting" - - local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' - local -r azure_repo_file='[azure-cli] -name=azure-cli -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=yes -gpgcheck=yes - -[azurecore] -name=azurecore -baseurl=https://packages.microsoft.com/yumrepos/azurecore -enabled=yes -gpgcheck=no' - - write_file azure_repo_filename azure_repo_file true -} - -# configure_selinux -configure_selinux() { - log "starting" - - local -r relabel="${1:-false}" - - already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" - semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" - chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - - if "$relabel"; then - restorecon -RF /var/log/* || log "$already_defined_ignore_error" - fi -} - -# configure_firewalld_rules -configure_firewalld_rules() { - log "starting" - - # https://access.redhat.com/security/cve/cve-2020-13401 - local -r prefix="/etc/sysctl.d" - local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" - local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" - - write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true - - local -r disable_core_filename="$prefix/01-disable-core.conf" - local -r disable_core_file="kernel.core_pattern = |/bin/true - " - write_file disable_core_filename disable_core_file true + # Key dictates the filename written in /etc/logrotate.d + local -rA logrotate_dropins=( + ["gateway"]="$gateway_log_file" + ) - sysctl --system + configure_logrotate logrotate_dropins + configure_selinux local -ra enable_ports=( "80/tcp" "8081/tcp" "443/tcp" ) - - log "Enabling ports ${enable_ports[*]} on default firewalld zone" - # shellcheck disable=SC2068 - for port in ${enable_ports[@]}; do - log "Enabling port $port now" - firewall-cmd "--add-port=$port" - done - - firewall-cmd --runtime-to-permanent -} - -# pull_container_images -pull_container_images() { - log "starting" - - # The managed identity that the VM runs as only has a single roleassignment. - # This role assignment is ACRPull which is not necessarily present in the - # subscription we're deploying into. If the identity does not have any - # role assignments scoped on the subscription we're deploying into, it will - # not show on az login -i, which is why the below line is commented. - # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions - - # Suppress emulation output for podman instead of docker for az acr compatability - mkdir -p /etc/containers/ - mkdir -p /root/.docker - touch /etc/containers/nodocker - - # This name is used in the case that az acr login searches for this in it's environment - local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" - - log "logging into prod acr" - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" - docker pull "$MDMIMAGE" - docker pull "$RPIMAGE" - docker pull "$FLUENTBITIMAGE" - - az logout -} - -# configure_system_services creates, configures, and enables the following systemd services and timers -# services -# fluentbit -# mdm -# mdsd -# arp-rp -# aro-dbtoken -# aro-monitor -# aro-portal -configure_system_services() { - configure_service_fluentbit - configure_service_mdm - configure_timers_mdm_mdsd - configure_service_aro_gateway "$1" - configure_service_mdsd -} - -# enable_aro_services enables all services required for aro rp -enable_aro_services() { - log "starting" - - local -ra aro_services=( - aro-gateway - auoms - azsecd - azsecmond - mdsd - mdm - chronyd - fluentbit + configure_firewalld_rules enable_ports + + local -r mdmimage="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -r rpimage="$RPIMAGE" + local -r fluentbit_image="$FLUENTBITIMAGE" + local -ra images=( + "$mdmimage" + "$rpimage" + "$fluentbit_image" ) - log "enabling gateway services ${aro_services[*]}" - # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do - log "Enabling $service now" - systemctl enable "$service.service" - done -} -# configure_service_fluentbit -configure_service_fluentbit() { - log "starting" - log "configuring fluentbit service" + pull_container_images images registry_config_file - mkdir -p /etc/fluentbit/ - mkdir -p /var/lib/fluent - - local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' local -r fluentbit_conf_file="[INPUT] Name systemd Tag journald @@ -488,277 +113,49 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - write_file fluentbit_conf_filename fluentbit_conf_file true - - local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' - local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" - - write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true - - local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' - - local -r fluentbit_service_file="[Unit] -After=network-online.target -Wants=network-online.target -StartLimitIntervalSec=0 - -[Service] -RestartSec=1s -EnvironmentFile=/etc/sysconfig/fluentbit -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --security-opt label=disable \ - --entrypoint /opt/td-agent-bit/bin/td-agent-bit \ - --net=host \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -v /etc/fluentbit/fluentbit.conf:/etc/fluentbit/fluentbit.conf \ - -v /var/lib/fluent:/var/lib/fluent:z \ - -v /var/log/journal:/var/log/journal:ro \ - -v /etc/machine-id:/etc/machine-id:ro \ - $FLUENTBITIMAGE \ - -c /etc/fluentbit/fluentbit.conf - -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=5 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file fluentbit_conf_filename fluentbit_conf_file true -} - -# configure_certs -configure_certs() { - log "starting" - - mkdir /etc/aro-rp - base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem - if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem - fi - chown -R 1000:1000 /etc/aro-rp - - # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not - # to honour SSL_CERT_FILE any more, heaven only knows why. - mkdir -p /usr/lib/ssl/certs - csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null - c_rehash /usr/lib/ssl/certs - -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning - local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" - local -r nodescan_agent_file="{ - \"Nice\": 19, - \"Timeout\": 10800, - \"ClientId\": \"\", - \"TenantId\": $AZURESECPACKVSATENANTID, - \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, - \"ProcessTimeout\": 300, - \"CommandDelay\": 0 - }" - - write_file nodescan_agent_filename nodescan_agent_file true -} - -# configure_service_mdm -configure_service_mdm() { - log "starting" - log "configuring mdm service" - - local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" - local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' -MDMIMAGE='$MDMIMAGE' -MDMSOURCEENVIRONMENT='$LOCATION' -MDMSOURCEROLE=gateway -MDMSOURCEROLEINSTANCE=\"$(hostname)\"" + configure_service_fluentbit fluentbit_conf_file fluentbit_image + local -r mdm_role="gateway" + configure_service_mdm mdm_role mdmimage - write_file sysconfig_mdm_filename sysconfig_mdm_file true - - mkdir -p /var/etw - local -r mdm_service_filename="/etc/systemd/system/mdm.service" - local -r mdm_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/mdm -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --entrypoint /usr/sbin/MetricsExtension \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -m 2g \ - -v /etc/mdm.pem:/etc/mdm.pem \ - -v /var/etw:/var/etw:z \ - $MDMIMAGE \ - -CertFile /etc/mdm.pem \ - -FrontEndUrl $MDMFRONTENDURL \ - -Logger Console \ - -LogLevel Warning \ - -PrivateKeyFile /etc/mdm.pem \ - -SourceEnvironment $MDMSOURCEENVIRONMENT \ - -SourceRole $MDMSOURCEROLE \ - -SourceRoleInstance $MDMSOURCEROLEINSTANCE -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file mdm_service_filename mdm_service_file true -} - -# configure_timers_mdm_mdsd -configure_timers_mdm_mdsd() { - log "starting" - - for var in "mdsd" "mdm"; do - local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" - local download_creds_service_file="[Unit] -Description=Periodic $var credentials refresh - -[Service] -Type=oneshot -ExecStart=/usr/local/bin/download-credentials.sh $var" - - write_file download_creds_service_filename download_creds_service_file true - - local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" - local download_creds_timer_file="[Unit] -Description=Periodic $var credentials refresh -After=network-online.target -Wants=network-online.target - -[Timer] -OnBootSec=0min -OnCalendar=0/12:00:00 -AccuracySec=5s - -[Install] -WantedBy=timers.target" - - write_file download_creds_timer_filename download_creds_timer_file true - done - - local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" - local -r download_creds_script_file="#!/bin/bash -set -eu - -COMPONENT=\$1 -echo \"Download \$COMPONENT credentials\" - -TEMP_DIR=\"\$(mktemp -d)\" -export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" - -echo \"Logging into Azure...\" -RETRIES=3 -while [[ \$RETRIES -gt 0 ]]; do - if az login -i --allow-no-subscriptions - then - echo \"az login successful\" - break - else - echo \"az login failed. Retrying...\" - let RETRIES-=1 - sleep 5 - fi -done - -trap \"cleanup\" EXIT - -cleanup() { - az logout - [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR - [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR -} - -if [[ \$COMPONENT = \"mdm\" ]]; then - CURRENT_CERT_FILE=\"/etc/mdm.pem\" -elif [[ \$COMPONENT\ = \"mdsd\" ]]; then - CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" -else - echo Invalid usage && exit 1 -fi - -SECRET_NAME=\"gwy-\${COMPONENT}\" -NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" -for attempt in {1..5}; do - az keyvault \ - secret \ - download \ - --file \"\$NEW_CERT_FILE\" \ - --id \"https://$KEYVAULTPREFIX-gwy.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ - && break - if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi -done - -if [ -f \$NEW_CERT_FILE ]; then - if [[ \$COMPONENT = \"mdsd\" ]]; then - chown syslog:syslog \$NEW_CERT_FILE - else - sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE - fi - - new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then - echo updating certificate for \$COMPONENT - chmod 0600 \$NEW_CERT_FILE - mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE - fi -else - echo Failed to refresh certificate for \$COMPONENT && exit 1 -fi" - - write_file download_creds_script_filename download_creds_script_file true - - chmod u+x /usr/local/bin/download-credentials.sh - - systemctl enable download-mdsd-credentials.timer - systemctl enable download-mdm-credentials.timer - - /usr/local/bin/download-credentials.sh mdsd - /usr/local/bin/download-credentials.sh mdm - - local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" - local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" - local -r watch_mdm_creds_service_file="[Unit] -Description=Watch for changes in mdm.pem and restarts the mdm service - -[Service] -Type=oneshot -ExecStart=/usr/bin/systemctl restart mdm.service - -[Install] -WantedBy=multi-user.target" - - write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true - - local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' - local -r watch_mdm_creds_path_file='[Path] -PathModified=/etc/mdm.pem - -[Install] -WantedBy=multi-user.target' + local -r gwy_dbtoken_service_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' +DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' +DOMAIN_NAME='$LOCATION.$CLUSTERPARENTDOMAINNAME' +AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' +DBTOKEN_URL='$DBTOKENURL' +MDM_ACCOUNT='$RPMDMACCOUNT' +MDM_NAMESPACE=Gateway +GATEWAY_DOMAINS='$GATEWAYDOMAINS' +GATEWAY_FEATURES='$GATEWAYFEATURES' +RPIMAGE='$RPIMAGE'" + configure_service_gateway gateway_logdir + + local -r mdsd_config_version="$GATEWAYMDSDCONFIGVERSION" + configure_service_mdsd mdm_role mdsd_config_version + local -r mdsd_role="gwy" + configure_timers_mdm_mdsd mdsd_role + + configure_certs mdm_role + + local -ra gateway_services=( + "aro-gateway" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + "download-mdsd-credentials.timer" + "download-mdm-credentials.timer" + ) - write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true + enable_services gateway_services - local -r watch_mdm_creds='watch-mdm-credentials.path' - systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" - systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" + reboot_vm } # configure_service_aro_rp -configure_service_aro_gateway() { +configure_service_gateway() { local -n log_dir="$1" log "starting" @@ -827,7 +224,7 @@ ExecStart=/usr/bin/docker run \ -v /run/systemd/journal:/run/systemd/journal \ -v /var/etw:/var/etw:z \ -v ${log_dir}:/ctr.log:z \ - \$RPIMAGE \ + $RPIMAGE \ gateway ExecStop=/usr/bin/docker stop -t 3600 %N TimeoutStopSec=3600 @@ -842,162 +239,6 @@ WantedBy=multi-user.target write_file aro_gateway_service_filename aro_gateway_service_file true } -# configure_service_aro_dbtoken -configure_service_aro_dbtoken() { - log "starting" - - local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' - local -r aro_dbtoken_service_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' -DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' -AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' -DBTOKEN_URL='$DBTOKENURL' -MDM_ACCOUNT='$RPMDMACCOUNT' -MDM_NAMESPACE=Gateway -GATEWAY_DOMAINS='$GATEWAYDOMAINS' -GATEWAY_FEATURES='$GATEWAYFEATURES' -RPIMAGE='$RPIMAGE'" - - write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true - - local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' - local -r aro_dbtoken_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/aro-gateway -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStartPre=/usr/bin/mkdir -p ${gateway_logdir} -ExecStart=/usr/bin/docker run \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -e ACR_RESOURCE_ID \ - -e DATABASE_ACCOUNT_NAME \ - -e AZURE_DBTOKEN_CLIENT_ID \ - -e DBTOKEN_URL \ - -e GATEWAY_DOMAINS \ - -e GATEWAY_FEATURES \ - -e MDM_ACCOUNT \ - -e MDM_NAMESPACE \ - -m 2g \ - -p 80:8080 \ - -p 8081:8081 \ - -p 443:8443 \ - -v /run/systemd/journal:/run/systemd/journal \ - -v /var/etw:/var/etw:z \ - -v ${gateway_logdir}:/ctr.log:z \ - \$RPIMAGE \ - gateway -ExecStop=/usr/bin/docker stop -t 3600 %N -TimeoutStopSec=3600 -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file aro_dbtoken_service_filename aro_dbtoken_service_file true -} - -# configure_service_mdsd -configure_service_mdsd() { - log "starting" - - local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" - mkdir "$mdsd_service_dir" - - local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" - local -r mdsd_override_conf_file="[Unit] -After=network-online.target" - - write_file mdsd_override_conf_filename mdsd_override_conf_file true - - local -r default_mdsd_filename="/etc/default/mdsd" - local -r default_mdsd_file="MDSD_ROLE_PREFIX=/var/run/mdsd/default -MDSD_OPTIONS=\"-A -d -r \$MDSD_ROLE_PREFIX\" - -export MONITORING_GCS_ENVIRONMENT='$MDSDENVIRONMENT' -export MONITORING_GCS_ACCOUNT='$RPMDSDACCOUNT' -export MONITORING_GCS_REGION='$LOCATION' -export MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault -export MONITORING_GCS_AUTH_ID='$MDSDCERTIFICATESAN' -export MONITORING_GCS_NAMESPACE='$RPMDSDNAMESPACE' -export MONITORING_CONFIG_VERSION='$GATEWAYMDSDCONFIGVERSION' -export MONITORING_USE_GENEVA_CONFIG_SERVICE=true - -export MONITORING_TENANT='$LOCATION' -export MONITORING_ROLE=gateway -export MONITORING_ROLE_INSTANCE=\"$(hostname)\" - -export MDSD_MSGPACK_SORT_COLUMNS=1\"" - - write_file default_mdsd_filename default_mdsd_file true - -} - -# run_azsecd_config_scan -run_azsecd_config_scan() { - log "starting" - - local -ar configs=( - "baseline" - "clamav" - "software" - ) - - log "Scanning configuration files ${configs[*]}" - # shellcheck disable=SC2068 - for scan in ${configs[@]}; do - log "Scanning config file $scan now" - /usr/local/bin/azsecd config -s "$scan" -d P1D - done -} - -# write_file -# Args -# 1) filename - string -# 2) file_contents - string -# 3) clobber - boolean; optional - defaults to false -write_file() { - local -n filename="$1" - local -n file_contents="$2" - local -r clobber="${3:-false}" - - if $clobber; then - log "Overwriting file $filename" - echo "$file_contents" > "$filename" - else - log "Appending to $filename" - echo "$file_contents" >> "$filename" - fi -} - -# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots -reboot_vm() { - log "starting" - - configure_selinux "true" - (sleep 30 && log "rebooting vm now"; reboot) & -} - -# log is a wrapper for echo that includes the function name -log() { - local -r msg="${1:-"log message is empty"}" - local -r stack_level="${2:-1}" - echo "${FUNCNAME[${stack_level}]}: ${msg}" -} - -# abort is a wrapper for log that exits with an error code -abort() { - local -ri origin_stacklevel=2 - log "${1}" "$origin_stacklevel" - log "Exiting" - exit 1 -} - export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 3c00da1185c..dfe02052521 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -8,116 +8,15 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { - parse_run_options "$@" + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + # shellcheck source=commonVMSS.sh + source commonVMSS.sh + create_required_dirs configure_sshd - configure_and_install_dnf_pkgs_repos - configure_disk_partitions - configure_logrotate - configure_selinux - - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - - configure_firewalld_rules - pull_container_images - configure_system_services - reboot_vm -} - -usage() { - local -n options="$1" - log "$(basename "$0") [$options] - -d Configure Disk Partitions - -p Configure rpm repositories, import required rpm keys, update & install packages with dnf - -l Configure logrotate.conf - -s Make selinux modifications required for ARO RP - -r Configure sshd - Allow password authenticaiton - -f Configure firewalld default zone rules - -u Configure systemd unit files for ARO RP - -i Pull container images - - Note: steps will be executed in the order that flags are provided - " -} - -# parse_run_options takes all arguements passed to main and parses them -# allowing individual step(s) to be ran, rather than all steps -# -# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline -parse_run_options() { - # shellcheck disable=SC2206 - local -a options=(${1:-}) - if [ "${#options[@]}" -eq 0 ]; then - log "Running all steps" - return 0 - fi - - local OPTIND - local -r allowed_options="dplsrfui" - while getopts ${allowed_options} options; do - case "${options}" in - d) - log "Running step configure_disk_partitions" - configure_disk_partitions - ;; - p) - log "Running step configure_and_install_dnf_pkgs_repos" - configure_and_install_dnf_pkgs_repos - ;; - l) - log "Running configure_logrotate" - configure_logrotate - ;; - s) - log "Running configure_selinux" - configure_selinux - ;; - r) - log "Running configure_sshd" - configure_sshd - ;; - f) - log "Running configure_firewalld_rules" - configure_firewalld_rules - ;; - u) - log "Running pull_container_images & configure_system_services" - configure_system_services - ;; - i) - log "Running pull_container_images" - pull_container_images - ;; - *) - usage allowed_options - abort "Unkown option provided" - ;; - esac - done - - exit 0 -} - -# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work -configure_sshd() { - log "starting" - log "setting ssh password authentication" - sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config - - systemctl reload sshd.service - systemctl is-active --quiet sshd || abort "sshd failed to reload" -} - -# configure_and_install_dnf_pkgs_repos -configure_and_install_dnf_pkgs_repos() { - log "starting" - - # transaction attempt retry time in seconds - local -ri retry_wait_time=60 - configure_rhui_repo retry_wait_time - create_azure_rpm_repos retry_wait_time + configure_rpm_repos retry_wait_time local -ar exclude_pkgs=( "-x WALinuxAgent" @@ -137,6 +36,8 @@ configure_and_install_dnf_pkgs_repos() { https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm ) + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + local -ra install_pkgs=( clamav azsec-clamav @@ -151,216 +52,15 @@ configure_and_install_dnf_pkgs_repos() { python3 ) - dnf_install_pkgs repo_rpm_pkgs retry_wait_time dnf_install_pkgs install_pkgs retry_wait_time -} - -# configure_rhui_repo -configure_rhui_repo() { - log "starting" - - local -ra cmd=( - dnf - update - -y - --disablerepo='*' - --enablerepo='rhui-microsoft-azure*' - ) - - log "running RHUI package updates" - retry cmd "$1" -} - -# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks -retry() { - local -n cmd_retry="$1" - local -n wait_time="$2" - - for attempt in {1..5}; do - log "attempt #${attempt} - ${FUNCNAME[2]}" - ${cmd_retry[@]} & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done -} - -# dnf_update_pkgs -dnf_update_pkgs() { - local -n excludes="$1" - log "starting" - - local -ra cmd=( - dnf - -y - ${excludes[@]} - update - --allowerasing - ) - - log "Updating all packages" - retry cmd "$2" -} - -# dnf_install_pkgs -dnf_install_pkgs() { - local -n pkgs="$1" - log "starting" - - local -ra cmd=( - dnf - -y - install - ${pkgs[@]} - ) - - log "Attempting to install packages: ${pkgs[*]}" - retry cmd "$2" -} - -# rpm_import_keys -rpm_import_keys() { - local -n keys="$1" - log "starting" - - - # shellcheck disable=SC2068 - for key in ${keys[@]}; do - if [ ${#keys[@]} -eq 0 ]; then - break - fi - local -a cmd=( - rpm - --import - -v - "$key" - ) - - log "attempt #$attempt - importing rpm repository key $key" - retry cmd "$2" && unset key - done -} - -# configure_disk_partitions -configure_disk_partitions() { - log "starting" - log "extending partition table" - - # Linux block devices are inconsistently named - # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here - physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" - growpart "$physical_disk" 2 - - log "extending filesystems" - log "extending root lvm" - lvextend -l +20%FREE /dev/rootvg/rootlv - log "growing root filesystem" - xfs_growfs / - - log "extending var lvm" - lvextend -l +100%FREE /dev/rootvg/varlv - log "growing var filesystem" - xfs_growfs /var -} - -# configure_logrotate clobbers /etc/logrotate.conf -configure_logrotate() { - log "starting" - - local -r logrotate_conf_filename='/etc/logrotate.conf' - local -r logrotate_conf_file='# see "man logrotate" for details -# rotate log files weekly -weekly - -# keep 2 weeks worth of backlogs -rotate 2 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we will rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} - -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -}' - - write_file logrotate_conf_filename logrotate_conf_file true -} - -# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file -create_azure_rpm_repos() { - log "starting" - - local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' - local -r azure_repo_file='[azure-cli] -name=azure-cli -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=yes -gpgcheck=yes - -[azurecore] -name=azurecore -baseurl=https://packages.microsoft.com/yumrepos/azurecore -enabled=yes -gpgcheck=no' - - write_file azure_repo_filename azure_repo_file true -} - -# configure_selinux -configure_selinux() { - log "starting" - - local -r relabel="${1:-false}" - - already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" - semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" - chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - - if "$relabel"; then - restorecon -RF /var/log/* || log "$already_defined_ignore_error" - fi -} - -# configure_firewalld_rules -configure_firewalld_rules() { - log "starting" - - # https://access.redhat.com/security/cve/cve-2020-13401 - local -r prefix="/etc/sysctl.d" - local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" - local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" - - write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true - - local -r disable_core_filename="$prefix/01-disable-core.conf" - local -r disable_core_file="kernel.core_pattern = |/bin/true - " - write_file disable_core_filename disable_core_file true + configure_dnf_cron_job + configure_disk_partitions - sysctl --system + # Key dictates the filename written in /etc/logrotate.d + # Present for future dropin files, also is required for configure_logrotate + local -rA logrotate_dropins=() + configure_logrotate logrotate_dropins + configure_selinux local -ra enable_ports=( "443/tcp" @@ -369,101 +69,19 @@ configure_firewalld_rules() { "2222/tcp" ) - log "Enabling ports ${enable_ports[*]} on default firewalld zone" - # shellcheck disable=SC2068 - for port in ${enable_ports[@]}; do - log "Enabling port $port now" - firewall-cmd "--add-port=$port" - done - - firewall-cmd --runtime-to-permanent -} - -# pull_container_images -pull_container_images() { - log "starting" - - # The managed identity that the VM runs as only has a single roleassignment. - # This role assignment is ACRPull which is not necessarily present in the - # subscription we're deploying into. If the identity does not have any - # role assignments scoped on the subscription we're deploying into, it will - # not show on az login -i, which is why the below line is commented. - # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions - - # Suppress emulation output for podman instead of docker for az acr compatability - mkdir -p /etc/containers/ - mkdir -p /root/.docker - touch /etc/containers/nodocker - - # This name is used in the case that az acr login searches for this in it's environment - local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" - - log "logging into prod acr" - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" - docker pull "$MDMIMAGE" - docker pull "$RPIMAGE" - docker pull "$FLUENTBITIMAGE" - - az logout -} + configure_firewalld_rules enable_ports -# configure_system_services creates, configures, and enables the following systemd services and timers -# services -# fluentbit -# mdm -# mdsd -# arp-rp -# aro-dbtoken -# aro-monitor -# aro-portal -configure_system_services() { - configure_service_fluentbit - configure_service_mdm - configure_timers_mdm_mdsd - configure_service_aro_rp - configure_service_aro_dbtoken - configure_service_aro_monitor - configure_service_aro_portal - configure_service_mdsd -} - -# enable_aro_services enables all services required for aro rp -enable_aro_services() { - log "starting" - - local -ra aro_services=( - "aro-dbtoken" - "aro-monitor" - "aro-portal" - "aro-rp" - "auoms" - "azsecd" - "azsecmond" - "mdsd" - "mdm" - "chronyd" - "fluentbit" + local -r mdmimage="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -r rpimage="$RPIMAGE" + local -r fluentbit_image="$FLUENTBITIMAGE" + local -ra images=( + "$mdmimage" + "$rpimage" + "$fluentbit_image" ) - log "enabling aro services ${aro_services[*]}" - # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do - log "Enabling $service now" - systemctl enable "$service.service" - done -} - -# configure_service_fluentbit -configure_service_fluentbit() { - log "starting" - log "configuring fluentbit service" + local -r registry_config_file="" + pull_container_images images registry_config_file - mkdir -p /etc/fluentbit/ - mkdir -p /var/lib/fluent - - local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' local -r fluentbit_conf_file="[INPUT] Name systemd Tag journald @@ -498,273 +116,39 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - write_file fluentbit_conf_filename fluentbit_conf_file true - - local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' - local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" - - write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true - - local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' - - local -r fluentbit_service_file="[Unit] -After=network-online.target -Wants=network-online.target -StartLimitIntervalSec=0 - -[Service] -RestartSec=1s -EnvironmentFile=/etc/sysconfig/fluentbit -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --security-opt label=disable \ - --entrypoint /opt/td-agent-bit/bin/td-agent-bit \ - --net=host \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -v /etc/fluentbit/fluentbit.conf:/etc/fluentbit/fluentbit.conf \ - -v /var/lib/fluent:/var/lib/fluent:z \ - -v /var/log/journal:/var/log/journal:ro \ - -v /etc/machine-id:/etc/machine-id:ro \ - $FLUENTBITIMAGE \ - -c /etc/fluentbit/fluentbit.conf - -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=5 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file fluentbit_conf_filename fluentbit_conf_file true -} - -# configure_certs -configure_certs() { - log "starting" - - mkdir /etc/aro-rp - base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem - if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem - fi - chown -R 1000:1000 /etc/aro-rp - - # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not - # to honour SSL_CERT_FILE any more, heaven only knows why. - mkdir -p /usr/lib/ssl/certs - csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null - c_rehash /usr/lib/ssl/certs - -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning - local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" - local -r nodescan_agent_file="{ - \"Nice\": 19, - \"Timeout\": 10800, - \"ClientId\": \"\", - \"TenantId\": $AZURESECPACKVSATENANTID, - \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, - \"ProcessTimeout\": 300, - \"CommandDelay\": 0 - }" - - write_file nodescan_agent_filename nodescan_agent_file true -} - -# configure_service_mdm -configure_service_mdm() { - log "starting" - log "configuring mdm service" - - local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" - local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' -MDMIMAGE='$MDMIMAGE' -MDMSOURCEENVIRONMENT='$LOCATION' -MDMSOURCEROLE=rp -MDMSOURCEROLEINSTANCE=\"$(hostname)\"" - - write_file sysconfig_mdm_filename sysconfig_mdm_file true - - mkdir -p /var/etw - local -r mdm_service_filename="/etc/systemd/system/mdm.service" - local -r mdm_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/mdm -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --entrypoint /usr/sbin/MetricsExtension \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -m 2g \ - -v /etc/mdm.pem:/etc/mdm.pem \ - -v /var/etw:/var/etw:z \ - $MDMIMAGE \ - -CertFile /etc/mdm.pem \ - -FrontEndUrl $MDMFRONTENDURL \ - -Logger Console \ - -LogLevel Warning \ - -PrivateKeyFile /etc/mdm.pem \ - -SourceEnvironment $MDMSOURCEENVIRONMENT \ - -SourceRole $MDMSOURCEROLE \ - -SourceRoleInstance $MDMSOURCEROLEINSTANCE -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file mdm_service_filename mdm_service_file true -} - -# configure_timers_mdm_mdsd -configure_timers_mdm_mdsd() { - log "starting" - - for var in "mdsd" "mdm"; do - local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" - local download_creds_service_file="[Unit] -Description=Periodic $var credentials refresh - -[Service] -Type=oneshot -ExecStart=/usr/local/bin/download-credentials.sh $var" - - write_file download_creds_service_filename download_creds_service_file true - - local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" - local download_creds_timer_file="[Unit] -Description=Periodic $var credentials refresh -After=network-online.target -Wants=network-online.target - -[Timer] -OnBootSec=0min -OnCalendar=0/12:00:00 -AccuracySec=5s - -[Install] -WantedBy=timers.target" - - write_file download_creds_timer_filename download_creds_timer_file true - done - - local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" - local -r download_creds_script_file="#!/bin/bash -set -eu - -COMPONENT=\$1 -echo \"Download \$COMPONENT credentials\" - -TEMP_DIR=\"\$(mktemp -d)\" -export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" - -echo \"Logging into Azure...\" -RETRIES=3 -while [[ \$RETRIES -gt 0 ]]; do - if az login -i --allow-no-subscriptions - then - echo \"az login successful\" - break - else - echo \"az login failed. Retrying...\" - let RETRIES-=1 - sleep 5 - fi -done - -trap \"cleanup\" EXIT - -cleanup() { - az logout - [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR - [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR -} - -if [[ \$COMPONENT = \"mdm\" ]]; then - CURRENT_CERT_FILE=\"/etc/mdm.pem\" -elif [[ \$COMPONENT\ = \"mdsd\" ]]; then - CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" -else - echo Invalid usage && exit 1 -fi - -SECRET_NAME=\"rp-\${COMPONENT}\" -NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" -for attempt in {1..5}; do - az keyvault \ - secret \ - download \ - --file \"\$NEW_CERT_FILE\" \ - --id \"https://$KEYVAULTPREFIX-svc.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ - && break - if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi -done - -if [ -f \$NEW_CERT_FILE ]; then - if [[ \$COMPONENT = \"mdsd\" ]]; then - chown syslog:syslog \$NEW_CERT_FILE - else - sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE - fi - - new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then - echo updating certificate for \$COMPONENT - chmod 0600 \$NEW_CERT_FILE - mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE - fi -else - echo Failed to refresh certificate for \$COMPONENT && exit 1 -fi" - - write_file download_creds_script_filename download_creds_script_file true - - chmod u+x /usr/local/bin/download-credentials.sh - - systemctl enable download-mdsd-credentials.timer - systemctl enable download-mdm-credentials.timer - - /usr/local/bin/download-credentials.sh mdsd - /usr/local/bin/download-credentials.sh mdm - - local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" - local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" - local -r watch_mdm_creds_service_file="[Unit] -Description=Watch for changes in mdm.pem and restarts the mdm service - -[Service] -Type=oneshot -ExecStart=/usr/bin/systemctl restart mdm.service - -[Install] -WantedBy=multi-user.target" + configure_service_fluentbit fluentbit_conf_file fluentbit_image + local -r monitor_role="rp" + configure_service_mdm monitor_role mdmimage + configure_timers_mdm_mdsd monitor_role + configure_service_aro_rp - write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true + configure_service_dbtoken rpimage + configure_service_aro_monitor rpimage + configure_service_aro_portal rpimage + local -r mdsd_rp_version="$RPMDSDCONFIGVERSION" + configure_service_mdsd monitor_role mdsd_rp_version - local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' - local -r watch_mdm_creds_path_file='[Path] -PathModified=/etc/mdm.pem + configure_certs monitor_role -[Install] -WantedBy=multi-user.target' + local -ra aro_services=( + "aro-dbtoken" + "aro-monitor" + "aro-portal" + "aro-rp" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + "download-mdsd-credentials.timer" + "download-mdm-credentials.timer" + ) - write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true + enable_services aro_services - local -r watch_mdm_creds='watch-mdm-credentials.path' - systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" - systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" + reboot_vm } # configure_service_aro_rp @@ -854,63 +238,12 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file aro_rp_service_filename aro_rp_conf_file true -} - -# configure_service_aro_dbtoken -configure_service_aro_dbtoken() { - log "starting" - - local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' - local -r aro_dbtoken_service_conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' -AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' -AZURE_GATEWAY_SERVICE_PRINCIPAL_ID='$GATEWAYSERVICEPRINCIPALID' -KEYVAULT_PREFIX='$KEYVAULTPREFIX' -MDM_ACCOUNT='$RPMDMACCOUNT' -MDM_NAMESPACE=DBToken -RPIMAGE='$RPIMAGE'" - - write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true - - local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' - local -r aro_dbtoken_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/aro-dbtoken -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -e AZURE_GATEWAY_SERVICE_PRINCIPAL_ID \ - -e DATABASE_ACCOUNT_NAME \ - -e AZURE_DBTOKEN_CLIENT_ID \ - -e KEYVAULT_PREFIX \ - -e MDM_ACCOUNT \ - -e MDM_NAMESPACE \ - -m 2g \ - -p 445:8445 \ - -v /run/systemd/journal:/run/systemd/journal \ - -v /var/etw:/var/etw:z \ - $RPIMAGE \ - dbtoken -ExecStop=/usr/bin/docker stop -t 3600 %N -TimeoutStopSec=3600 -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file aro_dbtoken_service_filename aro_dbtoken_service_file true + write_file aro_rp_service_filename aro_rp_service_file true } # configure_service_aro_monitor configure_service_aro_monitor() { + local -n image="$1" log "starting" log "configuring aro-monitor service" @@ -931,7 +264,7 @@ DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' KEYVAULT_PREFIX='$KEYVAULTPREFIX' MDM_ACCOUNT='$RPMDMACCOUNT' MDM_NAMESPACE=BBM -RPIMAGE='$RPIMAGE'" +RPIMAGE='$image'" write_file aro_monitor_service_conf_filename aro_monitor_service_conf_file true @@ -965,7 +298,7 @@ ExecStart=/usr/bin/docker run \ -m 2.5g \ -v /run/systemd/journal:/run/systemd/journal \ -v /var/etw:/var/etw:z \ - $RPIMAGE \ + $image \ monitor Restart=always RestartSec=1 @@ -979,6 +312,7 @@ WantedBy=multi-user.target" # configure_service_aro_portal configure_service_aro_portal() { + local -n image="$1" log "starting" local -r aro_portal_service_conf_filename='/etc/sysconfig/aro-portal' @@ -990,7 +324,7 @@ KEYVAULT_PREFIX='$KEYVAULTPREFIX' MDM_ACCOUNT='$RPMDMACCOUNT' MDM_NAMESPACE=Portal PORTAL_HOSTNAME='$LOCATION.admin.$RPPARENTDOMAINNAME' -RPIMAGE='$RPIMAGE'" +RPIMAGE='$image'" write_file aro_portal_service_conf_filename aro_portal_service_conf_file true @@ -1021,7 +355,7 @@ ExecStart=/usr/bin/docker run \ -p 2222:2222 \ -v /run/systemd/journal:/run/systemd/journal \ -v /var/etw:/var/etw:z \ - $RPIMAGE \ + $image \ portal Restart=always RestartSec=1 @@ -1029,104 +363,63 @@ RestartSec=1 [Install] WantedBy=multi-user.target" - write_file aro_portal_service_conf_filename aro_portal_service_conf_file true -} - -# configure_service_mdsd -configure_service_mdsd() { - log "starting" - - local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" - mkdir "$mdsd_service_dir" - - local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" - local -r mdsd_override_conf_file="[Unit] -After=network-online.target" - - write_file mdsd_override_conf_filename mdsd_override_conf_file true - - local -r default_mdsd_filename="/etc/default/mdsd" - local -r default_mdsd_file="MDSD_ROLE_PREFIX=/var/run/mdsd/default -MDSD_OPTIONS=\"-A -d -r \$MDSD_ROLE_PREFIX\" - -export MONITORING_GCS_ENVIRONMENT='$MDSDENVIRONMENT' -export MONITORING_GCS_ACCOUNT='$RPMDSDACCOUNT' -export MONITORING_GCS_REGION='$LOCATION' -export MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault -export MONITORING_GCS_AUTH_ID='$MDSDCERTIFICATESAN' -export MONITORING_GCS_NAMESPACE='$RPMDSDNAMESPACE' -export MONITORING_CONFIG_VERSION='$RPMDSDCONFIGVERSION' -export MONITORING_USE_GENEVA_CONFIG_SERVICE=true - -export MONITORING_TENANT='$LOCATION' -export MONITORING_ROLE=rp -export MONITORING_ROLE_INSTANCE=\"$(hostname)\" - -export MDSD_MSGPACK_SORT_COLUMNS=1\"" - - write_file default_mdsd_filename default_mdsd_file true - + write_file aro_portal_service_filename aro_portal_service_file true } -# run_azsecd_config_scan -run_azsecd_config_scan() { +# configure_service_aro_dbtoken +configure_service_dbtoken() { + local -n image="$1" log "starting" - local -ar configs=( - "baseline" - "clamav" - "software" - ) + local -r conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' +AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' +AZURE_GATEWAY_SERVICE_PRINCIPAL_ID='$GATEWAYSERVICEPRINCIPALID' +KEYVAULT_PREFIX='$KEYVAULTPREFIX' +MDM_ACCOUNT='$RPMDMACCOUNT' +MDM_NAMESPACE=DBToken +RPIMAGE='$image'" - log "Scanning configuration files ${configs[*]}" - # shellcheck disable=SC2068 - for scan in ${configs[@]}; do - log "Scanning config file $scan now" - /usr/local/bin/azsecd config -s "$scan" -d P1D - done -} + local -r conf_filename='/etc/sysconfig/aro-dbtoken' -# write_file -# Args -# 1) filename - string -# 2) file_contents - string -# 3) clobber - boolean; optional - defaults to false -write_file() { - local -n filename="$1" - local -n file_contents="$2" - local -r clobber="${3:-false}" + write_file conf_filename conf_file true - if $clobber; then - log "Overwriting file $filename" - echo "$file_contents" > "$filename" - else - log "Appending to $filename" - echo "$file_contents" >> "$filename" - fi -} + local -r service_file="[Unit] +After=network-online.target +Wants=network-online.target -# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots -reboot_vm() { - log "starting" +[Service] +EnvironmentFile=/etc/sysconfig/aro-dbtoken +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -e AZURE_GATEWAY_SERVICE_PRINCIPAL_ID \ + -e DATABASE_ACCOUNT_NAME \ + -e AZURE_DBTOKEN_CLIENT_ID \ + -e KEYVAULT_PREFIX \ + -e MDM_ACCOUNT \ + -e MDM_NAMESPACE \ + -m 2g \ + -p 445:8445 \ + -v /run/systemd/journal:/run/systemd/journal \ + -v /var/etw:/var/etw:z \ + $image \ + dbtoken +ExecStop=/usr/bin/docker stop -t 3600 %N +TimeoutStopSec=3600 +Restart=always +RestartSec=1 +StartLimitInterval=0 - configure_selinux "true" - (sleep 30 && log "rebooting vm now"; reboot) & -} +[Install] +WantedBy=multi-user.target" -# log is a wrapper for echo that includes the function name -log() { - local -r msg="${1:-"log message is empty"}" - local -r stack_level="${2:-1}" - echo "${FUNCNAME[${stack_level}]}: ${msg}" + local -r service_filename='/etc/systemd/system/aro-dbtoken.service' + write_file service_filename service_file true } -# abort is a wrapper for log that exits with an error code -abort() { - local -ri origin_stacklevel=2 - log "${1}" "$origin_stacklevel" - log "Exiting" - exit 1 -} export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}"