Public Access
Let a key move to another vault, and ask whether it goes with the host
Keys sync and keys are shared: SshKey is in the sync registry on both sides, the material rides in the sealed payload, and every generation of the vault key is wrapped to a new member. What was missing was the way in. Hosts and groups could move between vaults and keychain items could not, so a key typed into a personal vault before the team existed stayed there for good — and moving a host into the team's vault left it authenticating with something nobody else in that vault can read. The code said so and could do nothing about it: "the answer is usually to put a copy of that key in the destination vault", which meant pasting the private half into a second item and deleting the first. A private key on a clipboard, and two items nobody can tell apart afterwards. MoveAsync already existed on the generic repository and is now exposed for keys and passwords as it is for hosts and groups. What had to be built around it is the re-aim. An item re-sealed under another vault's key lands with an id of that vault's making, so every host bound to the old one and every group lending it as a default is left naming a tombstone — and a host bound to something its vault no longer holds refuses to connect rather than falling back to a typed password. A move without the re-aim would look like a success and break every machine on that key. It runs over every vault this session can write to, because a binding resolves across all of them, and it counts what it could not rewrite: an item from a newer client, or one in a vault this account may only read. Those are said in the sentence afterwards rather than swallowed. The host's move asks the question rather than deciding it. A binding resolves across vaults, so the moved host goes on working for the person who moved it whichever way this is answered; it is the colleagues they have just joined who hold one vault's key and cannot connect with a host whose key stayed behind. Unticked, and it stays that way on purpose: moving a key into a team's vault hands it to everybody holding that key, and this design does not default anybody into a disclosure. Under the box is the count of everything else that authenticates with that key, because a key twenty machines use is a different decision from one nothing else touches, and neither number is visible from the panel otherwise. The question is answered against the vault in the picker, so choosing a different destination re-asks it and a key already in the destination offers nothing. One thing fixed on the way. A host that inherited its key from its group arrived in the destination naming nothing at all — the group belongs to the vault it left — so a machine that connected before the move refused after it, with no sentence anywhere saying why. The resolved binding is now written onto the host as it crosses, and the stranded-binding warning reads the resolved binding too, which is the case where somebody is least likely to know a key is involved. MOVE is on both heads, for keys and passwords only: a tag, a bucket and a pin are read from the active vault alone, so "another vault" is not a question any of them has. Four tests cover the move and its re-aim, the host's move with the key brought and without it, and the inherited binding.
This commit is contained in:
@@ -712,6 +712,25 @@
|
||||
</ComboBox>
|
||||
<TextBlock Classes="body"
|
||||
Text="The host is re-encrypted with the other vault's key, so everybody who holds that key can read it and nobody else can. Its group and tags stay behind — both belong to the vault it is leaving." />
|
||||
|
||||
<!--
|
||||
◆ THE KEY. A binding resolves across vaults, so the host keeps working here whichever way this is
|
||||
answered — but the vault it has just joined holds one key, and a host whose own key stayed behind
|
||||
is one its new colleagues cannot connect with.
|
||||
|
||||
Unticked, because moving a key into a team's vault hands it to everybody who holds that vault's
|
||||
key: a disclosure is chosen, never defaulted into. The line under it is the count of what else
|
||||
uses that key, which is the difference between an obvious yes and an obvious no.
|
||||
-->
|
||||
<CheckBox IsChecked="{Binding BringsTheBindingAlong}" MinHeight="44"
|
||||
IsVisible="{Binding HasABindingToBring}">
|
||||
<TextBlock Classes="mono" FontSize="11.5" TextWrapping="Wrap"
|
||||
Text="{Binding BindingToBringQuestion}" />
|
||||
</CheckBox>
|
||||
<TextBlock Classes="body" TextWrapping="Wrap"
|
||||
IsVisible="{Binding HasABindingToBring}"
|
||||
Text="{Binding BindingToBringNote}" />
|
||||
|
||||
<Grid ColumnDefinitions="*,8,*">
|
||||
<Button Grid.Column="0" Classes="primary" Height="44" Content="MOVE"
|
||||
Command="{Binding ConfirmMoveHostCommand}" IsEnabled="{Binding !IsBusy}" />
|
||||
|
||||
@@ -149,8 +149,19 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Column="2" Classes="danger" Height="44" Width="104" Content="DELETE"
|
||||
Command="{Binding DeleteSelectedItemCommand}" />
|
||||
<!--
|
||||
MOVE beside it, and only where there is somewhere to move to — the rule the host's MOVE follows on
|
||||
this head, for the reason a phone has: there is no room to draw a button that answers with a
|
||||
refusal. It is the ghost of the pair rather than the danger one, because a move is undone by
|
||||
moving it back.
|
||||
-->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="8">
|
||||
<Button Classes="secondary" Height="44" Width="86" Content="MOVE"
|
||||
IsVisible="{Binding CanMoveSelectedItem}"
|
||||
Command="{Binding MoveSelectedItemCommand}" />
|
||||
<Button Classes="danger" Height="44" Width="104" Content="DELETE"
|
||||
Command="{Binding DeleteSelectedItemCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@@ -180,6 +191,47 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ============ ◆ moving it to another vault ============ -->
|
||||
<!--
|
||||
The desktop's panel, in the place the deletion question uses and never at the same time as it: MOVE
|
||||
disarms a pending deletion on the way in, and the buttons that ask either question are hidden while
|
||||
one is up.
|
||||
|
||||
Both sentences are here rather than only in the status line afterwards, which on a phone is one line at
|
||||
the bottom of a screen somebody has already navigated away from. The second one is the count of what
|
||||
points at this key — every one of them is re-aimed at the vault it moves to, and that is the part
|
||||
nobody can see from a keychain row.
|
||||
-->
|
||||
<Border Grid.Row="3" IsVisible="{Binding IsMovingItem}" Margin="12,4"
|
||||
Background="{StaticResource Panel}" BorderBrush="{StaticResource BorderMid}"
|
||||
BorderThickness="1" CornerRadius="12" Padding="14,12">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Classes="label" Text="MOVE TO VAULT" />
|
||||
<TextBlock Classes="mono" FontSize="12" TextWrapping="Wrap"
|
||||
Text="{Binding MovingItemLabel}" />
|
||||
<ComboBox HorizontalAlignment="Stretch" MinHeight="44"
|
||||
ItemsSource="{Binding MoveItemVaultChoices}"
|
||||
SelectedItem="{Binding SelectedMoveItemVault}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:VaultChoiceViewModel">
|
||||
<TextBlock Classes="mono" FontSize="12" Text="{Binding Display}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<TextBlock Classes="body" TextWrapping="Wrap"
|
||||
Text="It is re-encrypted with the other vault's key, so everybody who holds that key can read it and nobody in the vault it leaves can." />
|
||||
<TextBlock Classes="body" TextWrapping="Wrap"
|
||||
IsVisible="{Binding HasMovingItemUsage}"
|
||||
Text="{Binding MovingItemUsage}" />
|
||||
<Grid ColumnDefinitions="*,8,*" Margin="0,4,0,0">
|
||||
<Button Grid.Column="0" Classes="primary" Height="44" Content="MOVE"
|
||||
Command="{Binding ConfirmMoveItemCommand}" IsEnabled="{Binding !IsBusy}" />
|
||||
<Button Grid.Column="2" Classes="secondary" Height="44" Content="CANCEL"
|
||||
Command="{Binding CancelMoveItemCommand}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ============ the items ============ -->
|
||||
<Panel Grid.Row="4">
|
||||
|
||||
|
||||
Reference in New Issue
Block a user