Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

add /cloud/join for integration with BlueOS Cloud #2081

Closed
wants to merge 1 commit into from

Conversation

Williangalvani
Copy link
Member

@Williangalvani Williangalvani commented Sep 4, 2023

still WIP, we intend to keep the page hidden while we work on it.

@Williangalvani Williangalvani changed the title Cloud add /cloud/join for integration with BlueOS Cloud Sep 4, 2023
@Williangalvani Williangalvani force-pushed the cloud branch 2 times, most recently from 524f115 to 8758fce Compare September 4, 2023 17:37
@Williangalvani Williangalvani marked this pull request as ready for review September 6, 2023 16:01
}
},
async mounted() {
const result = await commander.command("python -c 'import machineid; print(machineid.hashed_id())'")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it better to have helper to provide such information on the frontend over doing python over ts ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it definitely is. actually I was thinking it could be done by linux2rest, what do you think?

Copy link
Member

@joaoantoniocardoso joaoantoniocardoso Sep 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ID uniquely identifies the host. It should be considered
"confidential", and must not be exposed in untrusted
environments, in particular on the network. If a stable unique
identifier that is tied to the machine is needed for some
application, the machine ID or any part of it must not be used
directly. Instead the machine ID should be hashed with a
cryptographic, keyed hash function, using a fixed,
application-specific key. That way the ID will be properly
unique, and derived in a constant way from the machine ID but
there will be no way to retrieve the original machine ID from the
application-specific one. The
sd_id128_get_machine_app_specific(3) API provides an
implementation of such an algorithm.

https://man7.org/linux/man-pages/man5/machine-id.5.html

So I guess we should pass an application key to it, like machineid.hashed_id({some-blueos-thing})

To avoid using commander, we could bind the /etc/machine-id as read-only to the BlueOs container.

Copy link
Member Author

@Williangalvani Williangalvani Sep 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except we dont want to use machine-id, right? since it does a pretty bad job at "uniquely identifying the host"...
I vote that at first we just hash the cpu serial. I have no strong feelings about that being confidential.

For it do actually be confidention, we'd have to implement the "join" logic mostly in the backend, though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vote to keep using machine-id if #2084 fixes the "duplication" issue.

Regarding the concern of better tracking software installed, a simple serial, machine id, will not be enough to prevent people from reusing paid things when changing hardware.

We will need something a lot more elegant, like a full certificate generated from multiple hardware information (maybe even allowing some drifting from the original if a component is changed ( ship of Theseus discussions soon ))

While the machine-id right now is being used only kinda as a username, @joaoantoniocardoso suggestion could still pay out in the future, so maybe we can add an application key to the function call.

Copy link
Member

@patrickelectric patrickelectric Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with pascal about the security concerns.
For now, what I can point is:

For a rasp we can use the serial number, and for everything else we could have custom support or use directly https://docs.rs/machineid-rs/latest/machineid_rs/, that should support everything necessary for hardware identification generation and add it in linux2rest as pointed by @Williangalvani for easy access API. For more information about crates capabilities, check https://docs.rs/machineid-rs/1.2.4/machineid_rs/enum.HWIDComponent.html

But, that may not fix the issue, since we are going to have only a local source that may not work reliable.

I vote for us to have an automatic request by blueos to blueos.cloud requesting an unique identifier based on the HARDWARE_IDENTIFIER.

HARDWARE_IDENTIFIER = `${HARDWARE_IDENTIFIER}-${LINUX_MACHINE_ID}`
BLUEOS_CLOUD_IDENTIFIER = request_blueos_cloud_identifier(HARDWARE_IDENTIFIER)
BLUEOS_IDENTIFIER = `${BLUEOS_CLOUD_IDENTIFIER}-${HARDWARE_IDENTIFIER}`

With that we ensure a global unique identifier with at least a single source of true.

Copy link
Member

@joaoantoniocardoso joaoantoniocardoso Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, there's a big difference here in the outcome of each of the methods... I'm still not sure if it's clear, let me try this:

What do we want to know?

A) We want to keep track of BlueOS installations

Use an asymmetric hashed /etc/machine-id with a key, they will change every time BlueOS is installed, meaning that the SD card can be transported to different vehicles we we will not notice it.

B) We want to keep track of the vehicle/robot unit

Create some asymmetric hash using reliable hardware information, like machineid-rs. This will result in no matter which SD card or installation, the vehicle/robot is always the same.

C) We want to keep track of both

Use two separate hashes, which allow us to keep track of both :)


@patrickelectric, in the case of your example, I didn't get what would be the default HARDWARE_IDENTIFIER. Also, we want to make sure that any HARDWARE_IDENTIFIER would produce a normalized string representing some asymmetric hashed information, with fixed length and ASCII-only characters, for consistency.

edit: Note that the (C) can be implemented in two separate steps.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HARDWARE_IDENTIFIER is generated during execution time, so with that we're going to check if the two computers share the same CLOUD unique identifier with different hardware identification. That'll happen on the case where the sdcard is cloned.

How HARDWARE_IDENTIFIER will be created depend on us. Right now, I would use the pi serial number + machineid-rs (SystemID, CPUCores, MacAddress, CPUID), where the machineid-rs would be the standard way of doing it if there are no custom support for the identified system.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HARDWARE_IDENTIFIER is generated during execution time, so with that we're going to check if the two computers share the same CLOUD unique identifier with different hardware identification. That'll happen on the case where the sdcard is cloned.

How HARDWARE_IDENTIFIER will be created depend on us. Right now, I would use the pi serial number + machineid-rs (SystemID, CPUCores, MacAddress, CPUID), where the machineid-rs would be the standard way of doing it if there are no custom support for the identified system.

Okay, so you want to do only (B)?

Copy link
Member

@patrickelectric patrickelectric Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HARDWARE_IDENTIFIER is generated during execution time, so with that we're going to check if the two computers share the same CLOUD unique identifier with different hardware identification. That'll happen on the case where the sdcard is cloned.
How HARDWARE_IDENTIFIER will be created depend on us. Right now, I would use the pi serial number + machineid-rs (SystemID, CPUCores, MacAddress, CPUID), where the machineid-rs would be the standard way of doing it if there are no custom support for the identified system.

Okay, so you want to do only (B)?

It's C, where we keep track of both, we ask BLUEOS_CLOUD_IDENTIFIER that is always unique. With this, we are going to be sure that is always a single unique identifier per vehicle.

SD Card cloned

The HARDWARE_IDENTIFIER will not be the same when comparing to BLUEOS_CLOUD_IDENTIFIER on the cloud database, we are going to detect this case.

New SD Card, old registered hardware

The HARDWARE_IDENTIFIER will match but BLUEOS_CLOUD_IDENTIFIER not once connects to blueos.cloud. We are going to detect this case as well.

Both cases also help us identifier changes on hardware, cloned sd card and much more under the same user account if the user does a logging with the BLUEOS_IDENTIFIER to the same user.

core/frontend/src/store/commander.ts Outdated Show resolved Hide resolved
core/frontend/src/store/commander.ts Outdated Show resolved Hide resolved
core/frontend/src/store/commander.ts Outdated Show resolved Hide resolved
'Invalid token. Failed to link your vehicle to BlueOS Cloud ',
true,
)
} else if (error.response.status === 400) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else is not necessary, an early return can be performed.

core/frontend/src/views/CloudView.vue Outdated Show resolved Hide resolved
true,
)
// TODO: save this securely on a backend or file instead of bag
bag.setData('vehicle.cloud', { token: this.cloud_token })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this information is going to be used ? Does this PR work ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now it just validates the token with the backend and stores it locally. it will only be consumed in subsequent PRs

@Williangalvani
Copy link
Member Author

I think we decided to have this be in an extension together with major tom, is that right?

@patrickelectric
Copy link
Member

I think we decided to have this be in an extension together with major tom, is that right?

yes

@voorloopnul
Copy link
Contributor

voorloopnul commented Nov 10, 2023

I'm hoping to not have a web service running in the major_tom extension, just a daemon, so if we can have the token/auth process on blueos itself, I'll not complain :D

Also, I think we discussed before that the cloud joining would soon happen in the wizard, not sure how easy it is to mix things being hosted as an extension with the overall UI of BlueOS.

@Williangalvani @patrickelectric

@patrickelectric
Copy link
Member

I'm hoping to not have a web service running in the major_tom extension, just a daemon, so if we can have the token/auth process on blueos itself, I'll not complain :D

Also, I think we discussed before that the cloud joining would soon happen in the wizard, not sure how easy it is to mix things being hosted as an extension with the overall UI of BlueOS.

@Williangalvani @patrickelectric

Could we have only the joining / token processes in BlueOS and share that somehow with extensions ?

@voorloopnul
Copy link
Contributor

Yes, this PR does precisely that. It validates and saves the token in the bag.vehicle.cloud.
Also, this PR creates a blueOS URL "/cloud/join/" but doesn't advertise it anywhere; it is hidden, so only selected users can know and use it in the early stages, but later should be integrated in the wizard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants