Accessing EC2 instance after losing keypair

前端 未结 4 775
花落未央
花落未央 2021-01-02 09:37

I booted up an EC2 instance months ago and at that time I had the .pem key stored in my PC. The PC since crashed and I had to reinstall Windows on it and I don\'t have a bac

相关标签:
4条回答
  • 2021-01-02 10:03

    Not easily.

    Guidance on the forums indicate that you can kind of do it by generating a new key pair and then bringing up a new instance and mounting the volume from the original instance and installing the keypair in that volume. After that the original instance should be able to use the new keypair.

    According to this post on AWS Developer Forums it can be accomplished via:

    Creating a new keypair downloads the private key to your machine and the public key is stored in your AWS account. When you launch a new (linux) instance the public key is placed into the /root/.ssh/authorized_keys file (or /home/ubuntu/.ssh/authorized_keys for Canonical Ubuntu AMIs), allowing your private key access to the instance.

    Losing the private key can be fixed by logging in to the instance via another linux account if you have set one up.

    Alternatively, if you're running an EBS-backed instance then you can Stop it, attach the root EBS volume to another instance, and place a new public key into the authorized_keys file, then return the volume to the original (stopped) instance and Start the instance again.

    If none of these work, then - sorry - you're out of luck. It's called a key because you can't get in without it.

    0 讨论(0)
  • 2021-01-02 10:08

    When we loose private key, You can't login to that machine. However, there is an another way to access that machine by generating a new key-pair

    Please follow the below steps to recover the key.

    Step 1) Detach your root volume from your machine using AWS console.
    Step 2) Launch a fresh EC2 instance(Not from your old machine AMI)
    Step 3) Attach your old volume to new EC2 machine
    Step 4) Now login to new ec2 machine and mount the old EBS volume
    Step 5) Now go to that partition then visit home directory inside that machine and go to .ssh folder.
    Step 6) Now generate a new private and public key. Then paste public key into authorized_keys file.
    Step 7) Once you done with above steps, detach that volume from this ec2 machine.
    Step 8) Now attach this volume to your old machine as root volume
    Step 9) Now try to login to your old machine with the newly generated key.

    Hope it helps !!

    0 讨论(0)
  • 2021-01-02 10:12

    You have to create an image of an current instance and then use that image for launching new instance. All files and data would copy from that instance and use different key when launching instance, then access it with same key

    0 讨论(0)
  • 2021-01-02 10:16

    General idea: Use the AWS instance user-data to write a new ssh-rsa public key to /root/.ssh/authorized_keys. The cloud-init package installed on the linux instance needs to support the bootcmd directive. It worked for me with Ubuntu 16.04 and 18.04.

    User-data example:

    #cloud-config
    bootcmd:
     - echo 'ssh-rsa AAAAB3NzaC1... key-comment' > /root/.ssh/authorized_keys
    

    This can be done manually, e.g. generate a new key with PuTTYgen, and set the user-data on the EC2 instance via AWS console.

    Or automated, e.g. with 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 {
        // use the AWS console to create an AWS IAM user with ec2 permissions for your region, and generate security credentials
        String awsAccessKey = "...";
        String awsSecretKey = "...";
        Regions region = Regions.US_EAST_1;
        String instanceId = "i-...";
    
        File pemKeyFile = new File("private.key.pem");
        String keyComment = "key-generated-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
    
        KeyPair keyPair;
        if(pemKeyFile.exists()) {
          System.out.println("reusing existing RSA private key: " + pemKeyFile.getAbsolutePath());
          try(PEMParser pemParser = new PEMParser(new FileReader(pemKeyFile))) {
            keyPair = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair) pemParser.readObject());
          }
        }
        else {
          System.out.println("generating new RSA private key: " + pemKeyFile.getAbsolutePath());
          KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
          keyGen.initialize(2048);
          keyPair = keyGen.generateKeyPair();
          try(JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(pemKeyFile))) {
            pemWriter.writeObject(keyPair.getPrivate());
          }
        }
    
        String authorized_keys = to_authorized_keys_line(keyPair, keyComment);
        String userdata = "#cloud-config";
        userdata += "\n" + "bootcmd:";
        userdata += "\n" + " - echo '" + authorized_keys + "' > /root/.ssh/authorized_keys";
        String userdataBase64 = Base64.getEncoder().encodeToString(userdata.getBytes(StandardCharsets.UTF_8));
        System.out.println("AWS instance user-data (can also be set manually via the AWS console):");
        System.out.println(userdata);
    
        AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard().withRegion(region) //
            .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKey, awsSecretKey))).build();
    
        // stop, set userdata, start
        ec2.stopInstances(new StopInstancesRequest().withInstanceIds(instanceId));
        waitForInstanceState(ec2, instanceId, InstanceStateName.Stopped);
        ec2.modifyInstanceAttribute(new ModifyInstanceAttributeRequest().withInstanceId(instanceId).withUserData(userdataBase64));
        ec2.startInstances(new StartInstancesRequest().withInstanceIds(instanceId));
        waitForInstanceState(ec2, instanceId, InstanceStateName.Running);
    
        // optional: stop, clear userdata, start
    
        System.out.println("new IP: " + ec2.describeInstances(new DescribeInstancesRequest().withInstanceIds(instanceId)).getReservations()
            .get(0).getInstances().get(0).getPublicIpAddress());
    
        // next step: automate DNS update
      }
    
      private static void waitForInstanceState(AmazonEC2 ec2, String instanceId, InstanceStateName desiredState) throws Exception {
        String currentState = "?";
        while(!currentState.equals(desiredState.toString())) {
          Thread.sleep(3_000);
          currentState = ec2.describeInstances(new DescribeInstancesRequest().withInstanceIds(instanceId)).getReservations().get(0)
              .getInstances().get(0).getState().getName();
          System.out.println("instance state: " + currentState + " (waiting for " + desiredState + ")");
        }
      }
    
      /** https://stackoverflow.com/questions/3706177/how-to-generate-ssh-compatible-id-rsa-pub-from-java */
      private static String to_authorized_keys_line(KeyPair key, String keyComment) throws IOException {
        byte[] exponent = ((RSAPublicKey) key.getPublic()).getPublicExponent().toByteArray();
        byte[] modulus = ((RSAPublicKey) key.getPublic()).getModulus().toByteArray();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write(new byte[] { 0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a' });
        out.write(toUInt32(exponent.length));
        out.write(exponent);
        out.write(toUInt32(modulus.length));
        out.write(modulus);
        return "ssh-rsa " + Base64.getEncoder().encodeToString(out.toByteArray()) + " " + keyComment;
      }
    
      private static byte[] toUInt32(int value) {
        return new byte[] { (byte) (value >>> 24 & 0xff), (byte) (value >>> 16 & 0xff), (byte) (value >>> 8 & 0xff), (byte) (value & 0xff) };
      }
    }
    

    Finally test the connection, e.g. with FileZilla:

    0 讨论(0)
提交回复
热议问题