Why are the UUIDs from this AWS network socket backwards?

Question:

When you use the AWS API to run a command on a remote docker container (ECS), the AWS API gives you back a websocket to read the output of your command from. When using the aws command line utility (which also uses the AWS API), reading the websocket stream is handled by session-manager-plugin.

session-manager-plugin is written in GoLang, and I’ve been trying to rewrite parts of it in Python. I don’t speak GoLang, but I fumbled my way though adding some code to session-manager-plugin to output the raw binary data it is sending, and receiving when the binary is being used.

Essentially, the output of the command you ran is split up into messages, each one with headers, and a payload. One of the headers for each message is a messageID, which is a UUID. Each message needs to be acknowledged by telling the server that you’re received the message with that UUID.

The issue I’m having is that when analyzing the raw binary data, I can see that a message that was received with UUID b'x85xc3x12Pnx08xaf)xfdxbax1b8x1asMd' is being acknowledged by session-manager-plugin with a packet that says this:

b'{"AcknowledgedMessageType":"output_stream_data","AcknowledgedMessageId":"fdba1b38-1a73-4d64-85c3-12500a08af29","AcknowledgedMessageSequenceNumber":4,"IsSequentialMessage":true}'

To figure out what UUID b'x85xc3x12Pnx08xaf)xfdxbax1b8x1asMd' is in Python, I do this:

import uuid

print(str(uuid.UUID(bytes=b'x85xc3x12Pnx08xaf)xfdxbax1b8x1asMd')))
# 85c31250-0a08-af29-fdba-1b381a734d64

At first glance, the UUID of the message that was received, and the UUID of the message being acknowledged do not match, but if you look closely, you’ll see that the UUID of the original message that was received is reversed from the UUID being acknowledged. Sort of. In the 16 byte UUID, the first 8 bytes come after the last 8 bytes.

85c31250-0a08-af29fdba-1b381a734d64

fdba1b38-1a73-4d6485c3-12500a08af29

Is there any reason this would be happening? Am I decoding b'x85xc3x12Pnx08xaf)xfdxbax1b8x1asMd' wrong?

Note: As you can see from above, the UUID in the Acknowledgement packet is inside of JSON. If I was decoding it wrong, the whole thing would be gibberish.

Also note that this is just an analysis of a perfectly working session-manager-plugin communication stream. One way or another, this actually works. I’m just trying to figure out how so I can re-create it.

Asked By: John

||

Answers:

Looking at the source code for session-manager-plugin, it would appear it reads the first eight bytes as the least significant bytes, then reads the next eight bytes as the most significant bytes, then appends it in the order MSB, LSB. Seems to me like that would produce the behavior you’re seeing.

// getUuid gets the 128bit uuid from an array of bytes starting from the offset.
func getUuid(log log.T, byteArray []byte, offset int) (result uuid.UUID, err error) {
    byteArrayLength := len(byteArray)
    if offset > byteArrayLength-1 || offset+16-1 > byteArrayLength-1 || offset < 0 {
        log.Error("getUuid failed: Offset is invalid.")
        return nil, errors.New("Offset is outside the byte array.")
    }

    leastSignificantLong, err := getLong(log, byteArray, offset)
    if err != nil {
        log.Error("getUuid failed: failed to get uuid LSBs Long value.")
        return nil, errors.New("Failed to get uuid LSBs long value.")
    }

    leastSignificantBytes, err := longToBytes(log, leastSignificantLong)
    if err != nil {
        log.Error("getUuid failed: failed to get uuid LSBs bytes value.")
        return nil, errors.New("Failed to get uuid LSBs bytes value.")
    }

    mostSignificantLong, err := getLong(log, byteArray, offset+8)
    if err != nil {
        log.Error("getUuid failed: failed to get uuid MSBs Long value.")
        return nil, errors.New("Failed to get uuid MSBs long value.")
    }

    mostSignificantBytes, err := longToBytes(log, mostSignificantLong)
    if err != nil {
        log.Error("getUuid failed: failed to get uuid MSBs bytes value.")
        return nil, errors.New("Failed to get uuid MSBs bytes value.")
    }

    uuidBytes := append(mostSignificantBytes, leastSignificantBytes...)

    return uuid.New(uuidBytes), nil
}

Source Code

Answered By: Nick ODell
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.