The general idea is to use AWS instance user data to write the new ssh-rsa public key in /root/.ssh/authorized_keys. The cloud-init package installed on the linux instance must support the bootcmd directive. This worked for me with Ubuntu 16.04 and 18.04.
Example user data:
#cloud-config bootcmd: - echo 'ssh-rsa AAAAB3NzaC1... key-comment' > /root/.ssh/authorized_keys
This can be done manually, for example, generate a new key using PuTTYgen and set user data for the EC2 instance through the AWS console.
Or automated, for example, using Java, using the AWS EC2 Java SDK and Bouncy Castle :
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.RSAPublicKey; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.Date; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.services.ec2.AmazonEC2; import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.ModifyInstanceAttributeRequest; import com.amazonaws.services.ec2.model.StartInstancesRequest; import com.amazonaws.services.ec2.model.StopInstancesRequest; public class RecoverAwsEc2RootSshAccess { public static void main(String[] args) throws Exception {
Finally, check the connection, for example, using FileZilla:

Reto hรถhener
source share