564 Commits

Author SHA1 Message Date
dependabot[bot]
081880b3f7 Bump fsevents from 2.3.2 to 2.3.3
Bumps [fsevents](https://github.com/fsevents/fsevents) from 2.3.2 to 2.3.3.
- [Release notes](https://github.com/fsevents/fsevents/releases)
- [Commits](https://github.com/fsevents/fsevents/compare/v2.3.2...v2.3.3)

---
updated-dependencies:
- dependency-name: fsevents
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 21:00:04 -07:00
Daniel Farina
9fb4117e6b Use updated, and stable link for AlmaLinux
The old image path is now a 404.  This breaks provisioning AlmaLinux
VMs, and pages the operator.
2023-08-18 23:29:42 -07:00
dependabot[bot]
2fbcd30fba Bump puma from 6.3.0 to 6.3.1
Bumps [puma](https://github.com/puma/puma) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: puma
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-19 09:27:28 +03:00
dependabot[bot]
298a92bd8b Bump jiti from 1.19.1 to 1.19.3
Bumps [jiti](https://github.com/unjs/jiti) from 1.19.1 to 1.19.3.
- [Release notes](https://github.com/unjs/jiti/releases)
- [Changelog](https://github.com/unjs/jiti/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unjs/jiti/compare/v1.19.1...v1.19.3)

---
updated-dependencies:
- dependency-name: jiti
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-19 09:26:33 +03:00
Enes Cakir
ded1be856a Fix available storage size update while destroying vm
We increase available_storage_gib at vm_host update query. But we delete
vm storage volumes before this query. So `vm.storage_size_gib` returns 0

We need to fix value for production hosts.
2023-08-18 23:19:29 +03:00
Furkan Sahin
39f8a9d2b8 Update nic_nexus to use subject_is for nic 2023-08-18 13:30:04 +02:00
Enes Cakir
aa1affaa62 Add support email to UI
We don't have public documentation for API yet. I replaced them with
support email links.

Fixes #466
2023-08-18 13:31:15 +03:00
Furkan Sahin
c764829a43 Adds an explanation to hetzner api for not fetching additional IPv6s
Recently we realized that when we added an IPv6 block (additional, by mistake),
the VmHost.create_addresses did not create the ipv6 block entity in the
database. Looking into the pull_ips, I realized that the ipv6 blocks come with
active_server_ip as the main ipv6 address of the server, not the ipv4. Since the
find_matching_ips function filters the ip addresses according to the host
address in sshable, this was expected. It's harmless for now but we should
tackle this once we start implementing extra ipv6 block support. That's why the
comment is added to show guidance for future.
2023-08-17 13:26:50 +02:00
Furkan Sahin
9e01c36ffd Auto rekeys every 24 hours
We start to rekey the whole mesh every 24 hour automatically.
2023-08-17 09:42:21 +02:00
Furkan Sahin
85420ccc5a Private Subnet IpsecTunnel rekeying
With this commit, we introduce the mechanism to replace the encryption
keys for existing ipsec tunnels. Here is the detailed explanation of the
work;
1. Private Subnet nexus hops to the refresh_keys state when needed. Here
we are going through a preparation phase. We start producing new
encryption keys, SPIs and reqids for the new state and policy objects.
At the end of the day, we write the new encryption keys, SPIs and the
reqids to the nic entities.  So, for every nic in the system, we prepare
the new parameters at the private subnet level.
2. Trigger NicNexus to start rekeying.
3. NicNexus buds RekeyNicTunnel to create the SA objects for inbound
packets.  This part is important. Let me explain the current state of
the tunnelling in detail here. Please refer to the end of the commit
message.
3. The RekeyNic prog in  setup_inbound state, first finds all the state
objects required to be created at the destination end. This way, no
matter when the source policy/state is updated, the receiving end will
be ready with the encryption key.
4. Once everyone creates their receiving end state objects, we switch to
update the sender (aka outbound). This ping-pong is managed via
SubnetNexus by checking the state of NicNexus strands and using
semaphores to progress the state machine. This part of the code means
any packet that is being created at this moment, will be encrypted with
the new keys.
5. Once everyone in the mesh has created/updated their sender policies
and state objects. We go ahead and drop the state objects that are not
referenced by any policy.

Ipsec Tunneling
Each tunnel has two ends <source_nic> and <destination_nic>. For a
tunnel to work, both ends need to know about the encryption key so that
they can either encrypt or decrypt the packet. However, the encryption
key is not sent over with the packet. Therefore, the key must exist
locally in both systems. How does it work? Firstly, I should tell you
about the 2 objects we use to implement ipsec tunnels.
1. Policy:
Policies are used to capture packages and apply encryption. The way it
works is easy. All the packets are observed and if there is a packet
that matches one of the policies we created, we capture the reqid from
the policy. The reqid is the unique identifier of a state object that
has the encryption key information. Therefore, if a policy is matched,
we get the reqid from the policy, find the matching state object and
encrypt the packet using the encryption key, send it to the networking
stack again.
2. State:
States are there to store the encryption key information. They also have
fields like spi and reqid. reqid is mentioned in the policy part, so,
for outgoing connections, reqid is used to identify the encryption key.
For incoming connections, that is spi because spi is sent with the
packet in the header so that when receiving end gets the packet, finds a
matching policy, the spi is read from the header and the encryption key
is identified. This gives us the flexibility of using multiple state
objects for 1 tunnel. Also, handy for the rekeying process.
2023-08-17 09:38:44 +02:00
Furkan Sahin
15dedc95c6 Add Hetzner Server Reset API support
In development, now we can reset the host server programmatically. For this to
work properly, you should make sure all the VMs are destroyed. Call VmHost.reset
function and then set the strand label to "start". It will give you a fresh
new host.
2023-08-17 09:37:54 +02:00
Enes Cakir
1026185d3f Hide sidebar items when no permission
To decide show sidebar item to user, we need to check user's permission
on project. We check one by one, but I don't want it. It runs a query
for each check.

I made `actions` argument optional in our authorization query. If it's
not provided, it returns all matched policies that user has permission
on given object. So we can fetch this list once, and check permission
from it.

Also we don't show create buttons if user doesn't have create permission
for Vm or Private Subnet.

Fixes #436
2023-08-16 17:09:39 +03:00
Ozgun Erdogan
5e860f5fb5 Update README.md
Readme edits based on feedback.
- Include link to managed platform
- Update steps to use the open and free version
- Update benefits section and include use-cases
- Refresh list of available services
- Add FAQ
2023-08-16 14:59:15 +03:00
dependabot[bot]
8fa0b51936 Bump postcss from 8.4.27 to 8.4.28
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.27 to 8.4.28.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.27...8.4.28)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-16 10:19:25 +03:00
Furkan Sahin
c7cce05044 Update subnet_nexus to use subject_is for private_subnet 2023-08-16 08:52:02 +02:00
Burak Yucesoy
fb554b5883 Restrict allowed OS user names
Different operating systems have different conventions. Below are reasonable
restrictions that works for most (all?) systems.
- Max length 32
- Only lowercase letters, numbers, hyphens and underscore
- Not start with a hyphen or number
2023-08-15 16:40:41 +03:00
Furkan Sahin
2d6fe9c858 Wait until VM is sshable before declaring running
We introduce a new state to verify the vm is up, running and the ssh agent is
up. We perform a quick, doomed to fail ssh command and simply check the output.
If it returns "Host key verification failed.", it means ssh-agent is also up
and responsive.
2023-08-15 14:13:26 +02:00
dependabot[bot]
88c21a1729 Bump roda from 3.70.0 to 3.71.0
Bumps [roda](https://github.com/jeremyevans/roda) from 3.70.0 to 3.71.0.
- [Changelog](https://github.com/jeremyevans/roda/blob/master/CHANGELOG)
- [Commits](https://github.com/jeremyevans/roda/compare/3.70.0...3.71.0)

---
updated-dependencies:
- dependency-name: roda
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-15 08:30:52 +03:00
Enes Cakir
c5ac3f1892 Show sidebar on error page if user is authenticated
Fixes #439
2023-08-15 08:30:21 +03:00
Enes Cakir
c8b8b25e85 Show vm state as "deleting" after delete button clicked
This PR doesn't simply set display_state as "deleting" at "destroy"
label because our operations are async. When user clicked "delete"
button, web service increases "destroy" semaphore, and respirate moves
nexus to destroy label. Until respirate fetches strand and run, state
isn't changed. In addition, destroying vm is quick, so probably vm's
disappeared when user reload page again.

To fix this delayed display_state issue, I override method to decide
display state for some special semaphores. In this PR, if "destroy"
semaphore is increased, vm.display_state returns "deleting" immediately.

I added `one_to_many :semaphores` relation to model to use eager loading.
Otherwise fetching semaphores for each vm separately at vm listing page
causes N+1 query issue.

Instead of all this mambo jambo, I might just update display_state as
"deleting" at place where we increase destroy semaphore. This place is
route file. Updating vm model at outside of its nexus felt like antipattern.
I didn't do that.

Fixes #438
2023-08-15 08:30:10 +03:00
Burak Yucesoy
48b5cdd374 Update billing rates to reflect uplink cost
In previous billing rates, uplink cost was miscalculated. With the correct
calculation customer facing price is increasing approximatelly $3 per core.
2023-08-14 20:31:50 +03:00
Enes Cakir
658e562ac8 Add "Dedicated CPU" mark to vm creation page
We are giving users dedicated vCPUs rather than over-provisioned ones.
2023-08-14 17:23:10 +03:00
Furkan Sahin
e26162f8df Fail fast in case of delete request for a subnet with VMs 2023-08-14 14:32:30 +02:00
Enes Cakir
250d5029d9 Add auto-refresh to vm show and index page
Users need to refresh the page manually to see if VM creation is
completed.

I added auto-refresh to VM creation and VM listing page. It reloads page
every 10 seconds.

Fixes #437
2023-08-14 09:57:29 +03:00
Enes Cakir
d15b126643 Show project's dashboard to user when added to project
Fixes #440
2023-08-14 09:57:04 +03:00
dependabot[bot]
acb83e0ed2 Bump nokogiri from 1.15.3 to 1.15.4
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.15.3 to 1.15.4.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.15.3...v1.15.4)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-13 17:16:14 -07:00
dependabot[bot]
57f04b8191 Bump stripe from 8.6.0 to 8.7.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 8.6.0 to 8.7.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v8.6.0...v8.7.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-13 17:16:03 -07:00
Daniel Farina
ea20a18ea3 Update Postgres point release to 15.4
While updating Node, I figured I may as well update Postgres.
2023-08-12 19:28:36 -07:00
Daniel Farina
138a770fdd Update Node
Not motivated by anything in particular, but I was experimenting with
some node programs and so I became aware there was a new version.
2023-08-12 19:28:36 -07:00
Enes Cakir
f90e9f6ab8 Increase test coverage of CloverBase
`freeze` override is in CloverVase so CloverWeb and CloverApi have this
new version. But we are freezing Clover not nested ones.

I moved this version of freeze to Clover

We should not call `DB.freeze` for tests too, because it blocks to
CloverWeb/CloverApi to enable new plugins that use new pg extensions.
2023-08-11 22:00:19 +03:00
Enes Cakir
4992a426e0 Show selected location's private subnets while creating vm
We need to decide to show which private subnets dynamically depending on
selected location. So it requires JavaScript code. We need to pass list
of subnets for that location to frontend code. There are two ways: pass
statically when page is rendered or pass dynamically via an ajax HTTP
request. Latter one requires an extra endpoint on backend to return
subnets. I implemented first option. If number of subnets increased too
much for each location we can consider fetching dynamically for selected
location.

Safari doesn't allow hiding select options, because of that we are
disabling them.
2023-08-11 16:08:02 +03:00
Furkan Sahin
472a15e516 Remove SPI from policy creation
SPI is not really necessary in policies. For outgoing connections, once the
template is matched the correct SA is identified locally via reqid. For
incoming connections, if the template matches, spi is already in the header
of the packet, which is used to match the correct SA. Therefore, we do not need
spi in policy.
We also set the reqid for to 0 for the destination. That way, the incoming
packet can be matched flexibly with the correct SA. reqid 0 means, no reqid
preference.
When we implement rekeying, this change will be handy since we won't be dealing
with destination policies separately.
2023-08-11 10:56:27 +02:00
Furkan Sahin
4f95dfa574 Start encrypting and forgetting nic encryption key
With this commit, we start to store encryption key in the database in encrypted
form instead of plain text. We also start to clean encryption key from the
database at the end of the mesh refreshing.
2023-08-11 10:52:48 +02:00
Burak Yucesoy
4575ce4de6 Use proc as stack's default value
Without proc, default_value is shared for all instances of the Strand and when
one of the callers of Strand.new updates the value of stack, it also modifies
the default value.
2023-08-11 11:51:30 +03:00
Enes Cakir
3c1698d702 Fix duplicate CloverBase requiring
CloverBase is required two times in CloverWeb/CloverApi files probably
by mistake. Also we can move it to loader, but loader expects to module
name and filename matched. I renamed it as `clover_base.rb`.
2023-08-11 11:37:28 +03:00
Enes Cakir
84d3eb6273 Add IPv4 pricing to UI
I made location based pricing helper on UI more generic at 247c987.

When you add `.location-based-price` class and `data-amount`,
`data-resource-type`, `data-resource-family` data attributes to an input,
it updates location based when changed.

I refactored checkbox component little bit to add this attributes to
options.

Also I added a description to IPv4 input.
2023-08-11 11:34:19 +03:00
Enes Cakir
8edfc4b2d6 Do not allow to create Vm without valid payment method
If project doesn't have any valid payment method, we don't allow to
create new virtual machines.
2023-08-11 11:33:06 +03:00
Enes Cakir
6dbf0d1d39 Introduce billing details
We need to get billing information from user to charge them at end of the
month.

We decided to use Stripe as payment provider. It has lots of features.
We can use low level APIs or some predefined UI from Stripe. We can keep
some of the information on our database too or keep all data at Stripe
and just keep Stripe identifier. I tried to find balance between them.
Then decided to keep all personal data on Stripe and we only keep Stripe
resource identifiers. It helps us to avoid GDPR issues. Also it helps to
keep service secure, it prevent to leak confidential data in dump or
logs.

Stripe has two resources: customer and payment method. We need to save
credit card information of users before they create any resource. Then
we will charge them using these information.

We have new two models: BillingInfo and PaymentMethod. BillingInfo is
corresponding for customer on Stripe side. We keep stripe_id for both
objects.

Each project has a BillingInfo. BillingInfo can be shared by projects.
So user can associate same BillingInfo with multiple project. But
currently I designed UI and models as each BillingInfo attached to
single project. We can relax it based on customer feedbacks.

BillingInfo has invoice details such as name, address, country etc. at
Stripe. PaymentMethod has metadata about credit card at Stripe.
PaymentMethod has order column, users can set a priority for payment
methods. We can try to charge them in order.

We collect initial BillingInfo and PaymentMethod details on Stripe's UI.
We tried to decrease friction for new users. We create Checkout session
with setup mode. It's Stripe's UI for saving customer and credit card
details. Stripe returns success url with session id.

After creation we use our UI to update customer details. Stripe's
Checkout session doesn't support updating customer details.

If STRIPE_SECRET_KEY isn't provided, billing is disabled.
2023-08-11 11:33:06 +03:00
Hadi Moshayedi
a9bd6794b0 Allocate VMs in a host with low memory/core ratio.
Previously we expected the host memory/core ratio be >= VMs
memory/core ratio. Now that we use 8GiB memory/core ratio,
allocating VMs in a an empty AX161 host failed, because it
had 4GiB memory/core ratio (32 cores and 128GiB memory).

But we could actually allocate VMs in that case by limiting
the number of cores that could be assigned to VMs instead.
For example in the AX161 case, instead of failing the allocation
we could limit ourselves only to 16 cores so we can still maintain
the 8GiB memory/core ratio.

This PR does that.
2023-08-11 00:24:40 -07:00
Enes Cakir
e226396e25 Change login page logo
We changed our description to "open and portable" from "open source
and portable".
2023-08-11 07:48:04 +03:00
dependabot[bot]
cbeaad61c7 Bump activesupport from 7.0.6 to 7.0.7
Bumps [activesupport](https://github.com/rails/rails) from 7.0.6 to 7.0.7.
- [Release notes](https://github.com/rails/rails/releases)
- [Changelog](https://github.com/rails/rails/blob/v7.0.7/activesupport/CHANGELOG.md)
- [Commits](https://github.com/rails/rails/compare/v7.0.6...v7.0.7)

---
updated-dependencies:
- dependency-name: activesupport
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-11 04:22:02 +03:00
Enes Cakir
c774005b3d Fix typo in price hash for vm creation 2023-08-11 01:43:54 +03:00
Furkan Sahin
5a2db437c2 Add hetzner API tests 2023-08-10 16:37:39 +02:00
Burak Yucesoy
113c66bfb3 Use YAML file for billing rates instead of a database table
Before this commit, billing rates were backed by a database table, because we
anticipated that the number of billing rates would be in the order of 10k as we
add new products and regions. However keeping this information in DB makes it
difficult to see current list of billing rates. Adding new billing raters also
requires database migration.

10k is high but still manageable as an in-memory array. We also have a quite a
long way until we reach that number. So, we are changing billing rates to be
backed by a YAML file.
2023-08-10 12:34:27 +03:00
dependabot[bot]
2a8a1efcb5 Bump rubocop-rspec from 2.23.1 to 2.23.2
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 2.23.1 to 2.23.2.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v2.23.1...v2.23.2)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-10 08:42:05 +03:00
Enes Cakir
7344ecb4c7 Create billing record for IPv4 address
IPv4 is a very scarce resource, and it starts to cost. Other cloud
providers charge extra when user enable IPv4. We decided to charge
$3 monthly for IPv4.
2023-08-09 16:12:37 +03:00
Furkan Sahin
c94617176a Update available storage size when destroying a Vm
We decrease vmhost available storage size when allocating a Vm. A Vm
will fail to allocate if there are not enough available storage.

Previously we didn't update the size of available storage when
destroying a Vm, which caused in not being able to allocate new Vms.

This PR fixes that by updating available storage size when destroying
a Vm.
2023-08-09 14:40:50 +02:00
Enes Cakir
5dfd9d347a Link vm storage size with vm size
Currently we allow user to select storage size. It's a slider between
10-100GB. 100GB is low, but what's the suitable maximum storage size is
another good question.

Allowing custom storage size introduces another allocation problem. An
user can create a virtual machine with high storage but low cores count.
It causes an idle VmHost that we can't allocate new virtual machine on
that because of not enough storage.

We decided to link storage size with core count. Some other cloud
providers do same thing. They give less storage for small machines.
Digital Ocean gives 25GB per core, and Hetzner Cloud gives 40GB per
core.
Our current AX161 machines have 1843 GB total storage, and 32 cores.
Currently I set 25GB storage for each cores. It means storage will be
32x25=800GB at maximum for now.

We can revisit our strategy when we introduce network based storage or
after several customer feedbacks.

We don't charge our customers for storage, because it's local storage
and it's already in monthly single core cost calculations.
2023-08-09 10:04:46 +03:00
dependabot[bot]
358d1980a0 Bump @jridgewell/resolve-uri from 3.1.0 to 3.1.1
Bumps [@jridgewell/resolve-uri](https://github.com/jridgewell/resolve-uri) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/jridgewell/resolve-uri/releases)
- [Commits](https://github.com/jridgewell/resolve-uri/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: "@jridgewell/resolve-uri"
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-09 09:34:32 +03:00
Hadi Moshayedi
42c19ca0f5 Update used hugepages when destroying a Vm.
We increase number of used hugepages when allocating a Vm. A Vm will
fail to allocate if there are not enough hugepages.

Previously we didn't update the number of hugepages when destroying
a Vm, which caused in not being able to allocate new Vms.

This PR fixes that by updating number of used hugepages when destroying
a Vm.
2023-08-08 20:28:51 -07:00